@oddin-gg/havik-player 2.27.0 → 2.27.2
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 +252 -235
- 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
|
@@ -975,26 +975,43 @@ var ht = class {
|
|
|
975
975
|
this.video.removeEventListener("timeupdate", e), this.video.removeEventListener("seeking", e);
|
|
976
976
|
};
|
|
977
977
|
}
|
|
978
|
-
};
|
|
979
|
-
function
|
|
980
|
-
let n =
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
978
|
+
}, gt = .25, _t = 1e3;
|
|
979
|
+
function vt(e, t) {
|
|
980
|
+
let n = null, r = (r) => {
|
|
981
|
+
n = r === "buffering" ? e.currentTime : null, t(r);
|
|
982
|
+
}, i = () => typeof performance < "u" ? performance.now() : Date.now(), a = i(), o = e.currentTime, s = () => {
|
|
983
|
+
let t = e.currentTime;
|
|
984
|
+
t > o && !e.seeking && !e.paused && (a = i()), o = t;
|
|
985
|
+
}, c = [
|
|
986
|
+
["playing", () => {
|
|
987
|
+
a = i(), o = e.currentTime, r("playing");
|
|
988
|
+
}],
|
|
989
|
+
["waiting", () => r("buffering")],
|
|
990
|
+
["stalled", () => {
|
|
991
|
+
if (e.paused) return;
|
|
992
|
+
let t = e.readyState < HTMLMediaElement.HAVE_FUTURE_DATA, n = i() - a >= _t;
|
|
993
|
+
(t || n) && r("buffering");
|
|
994
|
+
}],
|
|
995
|
+
["seeked", () => {
|
|
996
|
+
o = e.currentTime, n !== null && (n = e.currentTime);
|
|
997
|
+
}],
|
|
998
|
+
["timeupdate", () => {
|
|
999
|
+
s(), n !== null && !e.paused && !e.seeking && e.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA && e.currentTime - n >= gt && r("playing");
|
|
1000
|
+
}],
|
|
984
1001
|
["pause", () => {
|
|
985
|
-
e.ended ||
|
|
1002
|
+
e.ended || r("paused");
|
|
986
1003
|
}],
|
|
987
|
-
["ended", () =>
|
|
1004
|
+
["ended", () => r("ended")]
|
|
988
1005
|
];
|
|
989
|
-
for (let [t,
|
|
1006
|
+
for (let [t, n] of c) e.addEventListener(t, n);
|
|
990
1007
|
return () => {
|
|
991
|
-
for (let [t,
|
|
1008
|
+
for (let [t, n] of c) e.removeEventListener(t, n);
|
|
992
1009
|
};
|
|
993
1010
|
}
|
|
994
1011
|
//#endregion
|
|
995
1012
|
//#region src/core/engine/native.ts
|
|
996
|
-
var
|
|
997
|
-
function
|
|
1013
|
+
var yt = 2e3, bt = 3, z = 500, xt = 6e3, St = .25, Ct = 250, wt = .05, Tt = 4, Et = 12e3, Dt = .25, Ot = 1e3;
|
|
1014
|
+
function kt(e) {
|
|
998
1015
|
try {
|
|
999
1016
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
1000
1017
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -1010,7 +1027,7 @@ function V() {
|
|
|
1010
1027
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
1011
1028
|
return e || t;
|
|
1012
1029
|
}
|
|
1013
|
-
function
|
|
1030
|
+
function At() {
|
|
1014
1031
|
if (typeof navigator > "u" || !V()) return !1;
|
|
1015
1032
|
let e = navigator.userAgent ?? "";
|
|
1016
1033
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
@@ -1066,7 +1083,7 @@ var H = class {
|
|
|
1066
1083
|
type: "error",
|
|
1067
1084
|
error: L() ? new n("INTERNAL", 0, "native HLS playback error") : new n("NETWORK", 0, "native HLS playback error while offline"),
|
|
1068
1085
|
fatal: !0
|
|
1069
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
1086
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Mt(t.manifestUrl, t.analytics?.sid), e.load();
|
|
1070
1087
|
}
|
|
1071
1088
|
startLoad() {
|
|
1072
1089
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -1094,7 +1111,7 @@ var H = class {
|
|
|
1094
1111
|
};
|
|
1095
1112
|
this.onEncrypted = (n) => {
|
|
1096
1113
|
let a = n;
|
|
1097
|
-
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
1114
|
+
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = kt(a.initData), (async () => {
|
|
1098
1115
|
try {
|
|
1099
1116
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
1100
1117
|
initDataTypes: [a.initDataType],
|
|
@@ -1197,7 +1214,7 @@ var H = class {
|
|
|
1197
1214
|
if (this.cdnHost ||= mt(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1198
1215
|
n.isLive = !0;
|
|
1199
1216
|
let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
|
|
1200
|
-
Number.isFinite(r) && (n.atLiveEdge = r <=
|
|
1217
|
+
Number.isFinite(r) && (n.atLiveEdge = r <= Tt, !e.paused && r >= 0 && (n.latencySeconds = r));
|
|
1201
1218
|
} else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
|
|
1202
1219
|
return n;
|
|
1203
1220
|
}
|
|
@@ -1215,7 +1232,7 @@ var H = class {
|
|
|
1215
1232
|
return;
|
|
1216
1233
|
}
|
|
1217
1234
|
let t = this.hiddenSince;
|
|
1218
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1235
|
+
this.hiddenSince = null, t != null && e - t >= yt && this.armRefocus();
|
|
1219
1236
|
}, this.onPageShow = (e) => {
|
|
1220
1237
|
e.persisted && this.armRefocus();
|
|
1221
1238
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
@@ -1225,7 +1242,7 @@ var H = class {
|
|
|
1225
1242
|
let e = this.liveEnd(), t = U, n = t(), r = 0, i = () => {
|
|
1226
1243
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1227
1244
|
r += z;
|
|
1228
|
-
let a = this.liveEnd(), o = a != null && (e == null || a >= e +
|
|
1245
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + St), s = Math.max(r, t() - n) >= xt;
|
|
1229
1246
|
if (o || s && a != null) {
|
|
1230
1247
|
this.snapToLive();
|
|
1231
1248
|
return;
|
|
@@ -1245,9 +1262,9 @@ var H = class {
|
|
|
1245
1262
|
}, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
|
|
1246
1263
|
if (e.duration !== Infinity) return;
|
|
1247
1264
|
this.checkEndStale();
|
|
1248
|
-
let t =
|
|
1249
|
-
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >=
|
|
1250
|
-
},
|
|
1265
|
+
let t = jt(e, e.currentTime);
|
|
1266
|
+
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= wt) && (this.bufferedAdvancedAt = U()), this.lastBufferedEnd = t);
|
|
1267
|
+
}, Ct);
|
|
1251
1268
|
}
|
|
1252
1269
|
checkEndStale() {
|
|
1253
1270
|
if (this.endedEmitted) return;
|
|
@@ -1255,14 +1272,14 @@ var H = class {
|
|
|
1255
1272
|
this.lastTickAt = e;
|
|
1256
1273
|
let n = this.liveEnd();
|
|
1257
1274
|
if (n == null) return;
|
|
1258
|
-
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >=
|
|
1275
|
+
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= Dt;
|
|
1259
1276
|
this.lastSeekableEnd = n;
|
|
1260
1277
|
let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
|
|
1261
|
-
if (r || t >
|
|
1278
|
+
if (r || t > Ot || a || i.paused) {
|
|
1262
1279
|
this.edgeStampedAt = e;
|
|
1263
1280
|
return;
|
|
1264
1281
|
}
|
|
1265
|
-
e - (this.edgeStampedAt ?? e) >
|
|
1282
|
+
e - (this.edgeStampedAt ?? e) > Et && (this.endedEmitted = !0, this.deps.emit({
|
|
1266
1283
|
type: "ended",
|
|
1267
1284
|
reason: "stalled"
|
|
1268
1285
|
}));
|
|
@@ -1276,7 +1293,7 @@ var H = class {
|
|
|
1276
1293
|
liveEdgeEstimate() {
|
|
1277
1294
|
let e = this.deps.video;
|
|
1278
1295
|
if (e.duration !== Infinity) return null;
|
|
1279
|
-
let t = this.liveEnd(), n =
|
|
1296
|
+
let t = this.liveEnd(), n = jt(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1280
1297
|
if (n != null) {
|
|
1281
1298
|
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (U() - e) / 1e3));
|
|
1282
1299
|
(t == null || r > t) && (t = r);
|
|
@@ -1292,7 +1309,7 @@ var H = class {
|
|
|
1292
1309
|
snapToLive() {
|
|
1293
1310
|
let e = this.deps.video, t = this.liveEnd();
|
|
1294
1311
|
if (t == null) return;
|
|
1295
|
-
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t -
|
|
1312
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - bt, r);
|
|
1296
1313
|
try {
|
|
1297
1314
|
e.currentTime = i;
|
|
1298
1315
|
} catch {}
|
|
@@ -1313,7 +1330,7 @@ var H = class {
|
|
|
1313
1330
|
function U() {
|
|
1314
1331
|
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1315
1332
|
}
|
|
1316
|
-
function
|
|
1333
|
+
function jt(e, t) {
|
|
1317
1334
|
let n = e.buffered;
|
|
1318
1335
|
if (!n || !Number.isFinite(t)) return null;
|
|
1319
1336
|
for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
|
|
@@ -1322,7 +1339,7 @@ function kt(e, t) {
|
|
|
1322
1339
|
}
|
|
1323
1340
|
return null;
|
|
1324
1341
|
}
|
|
1325
|
-
function
|
|
1342
|
+
function Mt(e, t) {
|
|
1326
1343
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1327
1344
|
}
|
|
1328
1345
|
//#endregion
|
|
@@ -1339,13 +1356,13 @@ function W(e, t = Date.now()) {
|
|
|
1339
1356
|
}
|
|
1340
1357
|
//#endregion
|
|
1341
1358
|
//#region src/core/drm/xhrBody.ts
|
|
1342
|
-
var
|
|
1343
|
-
function
|
|
1359
|
+
var Nt = 4096;
|
|
1360
|
+
function Pt(e) {
|
|
1344
1361
|
if (!e || typeof e != "object") return;
|
|
1345
1362
|
let { response: t } = e;
|
|
1346
1363
|
if (typeof t == "string") return t;
|
|
1347
1364
|
let n;
|
|
1348
|
-
if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength >
|
|
1365
|
+
if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength > Nt)) try {
|
|
1349
1366
|
return new TextDecoder().decode(n);
|
|
1350
1367
|
} catch {
|
|
1351
1368
|
return;
|
|
@@ -1353,7 +1370,7 @@ function Mt(e) {
|
|
|
1353
1370
|
}
|
|
1354
1371
|
//#endregion
|
|
1355
1372
|
//#region src/core/engine/prefetch.ts
|
|
1356
|
-
var
|
|
1373
|
+
var Ft = 15e3, It = 5e3, Lt = 6, Rt = 4e3, zt = 2;
|
|
1357
1374
|
function G(e) {
|
|
1358
1375
|
try {
|
|
1359
1376
|
let t = new URL(e);
|
|
@@ -1362,7 +1379,7 @@ function G(e) {
|
|
|
1362
1379
|
return e;
|
|
1363
1380
|
}
|
|
1364
1381
|
}
|
|
1365
|
-
var
|
|
1382
|
+
var Bt = class {
|
|
1366
1383
|
cmcd;
|
|
1367
1384
|
entries = /* @__PURE__ */ new Map();
|
|
1368
1385
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1394,17 +1411,17 @@ var Rt = class {
|
|
|
1394
1411
|
let r = G(e);
|
|
1395
1412
|
if (this.entries.has(r)) return;
|
|
1396
1413
|
let i = this.perTrack.get(t) ?? 0;
|
|
1397
|
-
i >=
|
|
1414
|
+
i >= Lt || (this.perTrack.set(t, i + 1), this.start(r, this.withCmcd(e, t, n), !1, Ft), this.stats.started += 1);
|
|
1398
1415
|
}
|
|
1399
1416
|
prefetchHint(e, t) {
|
|
1400
1417
|
let n = G(e);
|
|
1401
1418
|
if (this.entries.has(n)) return;
|
|
1402
1419
|
let r = this.hints.get(t) ?? [];
|
|
1403
|
-
for (; r.length >=
|
|
1420
|
+
for (; r.length >= zt;) {
|
|
1404
1421
|
let e = r.shift();
|
|
1405
1422
|
e !== void 0 && this.drop(e) && (this.stats.hintDropped += 1);
|
|
1406
1423
|
}
|
|
1407
|
-
r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0,
|
|
1424
|
+
r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0, Rt), this.stats.hintStarted += 1;
|
|
1408
1425
|
}
|
|
1409
1426
|
dropHints(e) {
|
|
1410
1427
|
for (let t of this.hints.get(e) ?? []) this.drop(t) && (this.stats.hintDropped += 1);
|
|
@@ -1457,14 +1474,14 @@ var Rt = class {
|
|
|
1457
1474
|
}
|
|
1458
1475
|
}
|
|
1459
1476
|
};
|
|
1460
|
-
function
|
|
1477
|
+
function Vt(t, n) {
|
|
1461
1478
|
let r = typeof n == "function" ? n : e.DefaultConfig?.loader;
|
|
1462
1479
|
if (typeof r != "function") return;
|
|
1463
1480
|
class i extends r {
|
|
1464
1481
|
served = !1;
|
|
1465
1482
|
cancelled = !1;
|
|
1466
1483
|
entry;
|
|
1467
|
-
stats =
|
|
1484
|
+
stats = Ht();
|
|
1468
1485
|
load(e, n, r) {
|
|
1469
1486
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1470
1487
|
if (!i) {
|
|
@@ -1476,7 +1493,7 @@ function zt(t, n) {
|
|
|
1476
1493
|
i.hint ? t.stats.hintFailed += 1 : t.stats.failed += 1;
|
|
1477
1494
|
}, s = () => {
|
|
1478
1495
|
!this.cancelled && this.served && (i.abort.abort(), o(), this.served = !1, this.entry = void 0, super.load(e, n, r));
|
|
1479
|
-
}, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs ||
|
|
1496
|
+
}, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs || It, u = setTimeout(s, l);
|
|
1480
1497
|
i.headers.then(() => {
|
|
1481
1498
|
clearTimeout(u);
|
|
1482
1499
|
let e = c?.maxLoadTimeMs;
|
|
@@ -1509,7 +1526,7 @@ function zt(t, n) {
|
|
|
1509
1526
|
}
|
|
1510
1527
|
return i;
|
|
1511
1528
|
}
|
|
1512
|
-
function
|
|
1529
|
+
function Ht() {
|
|
1513
1530
|
return {
|
|
1514
1531
|
aborted: !1,
|
|
1515
1532
|
loaded: 0,
|
|
@@ -1533,10 +1550,10 @@ function Bt() {
|
|
|
1533
1550
|
}
|
|
1534
1551
|
};
|
|
1535
1552
|
}
|
|
1536
|
-
function
|
|
1553
|
+
function Ut(e) {
|
|
1537
1554
|
return e === "audio" ? "audio" : "main";
|
|
1538
1555
|
}
|
|
1539
|
-
function
|
|
1556
|
+
function Wt(e, t) {
|
|
1540
1557
|
let n = [];
|
|
1541
1558
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1542
1559
|
url: t.initSegment.url,
|
|
@@ -1553,7 +1570,7 @@ function Ht(e, t) {
|
|
|
1553
1570
|
});
|
|
1554
1571
|
return n;
|
|
1555
1572
|
}
|
|
1556
|
-
function
|
|
1573
|
+
function Gt(e) {
|
|
1557
1574
|
let t = e, n = t?.preloadHint;
|
|
1558
1575
|
if (!n || !t?.url || n.TYPE !== "PART" || n["BYTERANGE-START"] !== void 0 || n["BYTERANGE-LENGTH"] !== void 0) return null;
|
|
1559
1576
|
let r = n.URI;
|
|
@@ -1571,15 +1588,15 @@ function K(e, t) {
|
|
|
1571
1588
|
}
|
|
1572
1589
|
//#endregion
|
|
1573
1590
|
//#region src/core/engine/hls.ts
|
|
1574
|
-
function
|
|
1591
|
+
function Kt() {
|
|
1575
1592
|
return e.isSupported();
|
|
1576
1593
|
}
|
|
1577
|
-
var
|
|
1578
|
-
function
|
|
1594
|
+
var qt = 3, Jt = 1e6, Yt = 20, Xt = 1e4, Zt = 3, Qt = 5, $t = 3, en = 1e4, tn = 3e4, nn = 12e3, rn = 3e3, an = .02, on = 6e3, sn = .5, cn = 3, ln = .5, un = 1.1, dn = .25, fn = 5e3, pn = 4e3, mn = 2, hn = 5, gn = 2, _n = 2, vn = 4, yn = 4, bn = 2e3, xn = 3e4, Sn = 1, Cn = 2, wn = .5, Tn = .6, En = 2, Dn = 1.5, On = 1e4, kn = 18e4, An = .5, jn = 2;
|
|
1595
|
+
function Mn(e) {
|
|
1579
1596
|
let t = e.config ?? {};
|
|
1580
1597
|
return t.capLevelToPlayerSize === !0 || t.capLevelOnFPSDrop === !0;
|
|
1581
1598
|
}
|
|
1582
|
-
var q = 8,
|
|
1599
|
+
var q = 8, Nn = 12e4, Pn = 6e4;
|
|
1583
1600
|
function J(e, t, n) {
|
|
1584
1601
|
if (n <= 0 || t < 0 || t >= e.length) return t;
|
|
1585
1602
|
let r = (t, n) => e[t].width === e[n].width && e[t].height === e[n].height, i = (t) => {
|
|
@@ -1592,11 +1609,11 @@ function J(e, t, n) {
|
|
|
1592
1609
|
function Y() {
|
|
1593
1610
|
return typeof self < "u" && self.devicePixelRatio > 0 ? self.devicePixelRatio : 1;
|
|
1594
1611
|
}
|
|
1595
|
-
var
|
|
1596
|
-
function
|
|
1612
|
+
var Fn = .2, In = 30, Ln = 2, Rn = 2, zn = 2, Bn = 9, Vn = .5, Hn = 64, Un = 1e4, Wn = 8, Gn = .6, Kn = .4, qn = .4, Jn = 2, Yn = 6e4, X = .5, Xn = 3.5, Zn = 300;
|
|
1613
|
+
function Qn(e) {
|
|
1597
1614
|
return (e?.part ?? e?.frag)?.stats;
|
|
1598
1615
|
}
|
|
1599
|
-
function
|
|
1616
|
+
function $n() {
|
|
1600
1617
|
if (typeof navigator > "u") return 0;
|
|
1601
1618
|
try {
|
|
1602
1619
|
let e = navigator.connection?.rtt;
|
|
@@ -1605,20 +1622,20 @@ function Zn() {
|
|
|
1605
1622
|
return 0;
|
|
1606
1623
|
}
|
|
1607
1624
|
}
|
|
1608
|
-
function
|
|
1625
|
+
function er(e) {
|
|
1609
1626
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1610
1627
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1611
1628
|
return;
|
|
1612
1629
|
}
|
|
1613
|
-
e.liveSyncDuration ??=
|
|
1614
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1615
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1630
|
+
e.liveSyncDuration ??= zn;
|
|
1631
|
+
let t = Math.max(12, e.liveSyncDuration + Bn);
|
|
1632
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), tr(e, e.liveSyncDuration);
|
|
1616
1633
|
}
|
|
1617
|
-
function
|
|
1634
|
+
function tr(e, t) {
|
|
1618
1635
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1619
1636
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1620
1637
|
}
|
|
1621
|
-
var
|
|
1638
|
+
var nr = class {
|
|
1622
1639
|
name = "hls";
|
|
1623
1640
|
hls = null;
|
|
1624
1641
|
deps;
|
|
@@ -1771,7 +1788,7 @@ var er = class {
|
|
|
1771
1788
|
}
|
|
1772
1789
|
this.loadSuspended = !0;
|
|
1773
1790
|
}
|
|
1774
|
-
},
|
|
1791
|
+
}, fn));
|
|
1775
1792
|
}
|
|
1776
1793
|
resumeLoading() {
|
|
1777
1794
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1803,7 +1820,7 @@ var er = class {
|
|
|
1803
1820
|
let t = e.liveSyncPosition;
|
|
1804
1821
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1805
1822
|
let { video: n } = this.deps;
|
|
1806
|
-
n.currentTime <= t +
|
|
1823
|
+
n.currentTime <= t + Vn || (n.currentTime = t);
|
|
1807
1824
|
}
|
|
1808
1825
|
reanchorPartTimeline(e, t) {
|
|
1809
1826
|
let { frag: n, part: r } = t;
|
|
@@ -1815,7 +1832,7 @@ var er = class {
|
|
|
1815
1832
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1816
1833
|
if (!s) return;
|
|
1817
1834
|
let c = a.startPTS - s.start;
|
|
1818
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1835
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < an)) {
|
|
1819
1836
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1820
1837
|
i.fragmentHint?.setStart(i.fragmentHint.start + c), this.deps.debug === !0 && console.info(`havik-player: LL-HLS timeline re-anchored by ${c >= 0 ? "+" : ""}${c.toFixed(3)}s at sn ${n.sn} (level ${n.level})`);
|
|
1821
1838
|
}
|
|
@@ -1855,7 +1872,7 @@ var er = class {
|
|
|
1855
1872
|
return;
|
|
1856
1873
|
}
|
|
1857
1874
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1858
|
-
u = setTimeout(() => e(void 0),
|
|
1875
|
+
u = setTimeout(() => e(void 0), en);
|
|
1859
1876
|
});
|
|
1860
1877
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1861
1878
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1873,28 +1890,28 @@ var er = class {
|
|
|
1873
1890
|
this.prefetch?.destroy(), this.prefetch = null;
|
|
1874
1891
|
let p = !1, m = !1, h = u && this.deps.mediaDuringKey !== !1, g = this.deps.preloadHints !== !1;
|
|
1875
1892
|
if ((h || g) && !f.fLoader) {
|
|
1876
|
-
let e = new
|
|
1893
|
+
let e = new Bt({
|
|
1877
1894
|
sessionId: n.analytics?.sid,
|
|
1878
1895
|
contentId: n.matchUrn
|
|
1879
|
-
}), t =
|
|
1896
|
+
}), t = Vt(e, f.loader);
|
|
1880
1897
|
t && (this.prefetch = e, p = h, m = g, f.fLoader = t);
|
|
1881
1898
|
}
|
|
1882
|
-
|
|
1899
|
+
er(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;
|
|
1883
1900
|
let _ = new e(f);
|
|
1884
1901
|
if (this.hls = _, this.armHoldBack(_, f), _.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(_, t)), _.on(e.Events.MANIFEST_PARSED, () => {
|
|
1885
1902
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(_), this.measureLadder(_), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1886
1903
|
}), _.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1887
1904
|
t?.frag?.type === "main" && (this.kickKind !== "dead" && this.clearKick(), (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
1888
1905
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1889
|
-
},
|
|
1906
|
+
}, tn)));
|
|
1890
1907
|
}), _.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1891
1908
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1892
1909
|
}), _.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1893
1910
|
t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
|
|
1894
|
-
let n = t?.frag, r =
|
|
1911
|
+
let n = t?.frag, r = Qn(t), i = r?.loaded;
|
|
1895
1912
|
typeof i == "number" && (this.bytesLoaded += i), !this.reportedFirstBytes && typeof i == "number" && i > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1896
1913
|
let a = r?.loading;
|
|
1897
|
-
a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length >
|
|
1914
|
+
a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length > Hn && this.requestTimesMs.shift()), this.sampleHoldBack(t), this.sampleHeadroom(t);
|
|
1898
1915
|
let o = n?.url;
|
|
1899
1916
|
if (o) {
|
|
1900
1917
|
let e = ft(o);
|
|
@@ -1914,8 +1931,8 @@ var er = class {
|
|
|
1914
1931
|
let i = e;
|
|
1915
1932
|
if (!i?.live || !i.partList?.length || typeof i.edge != "number") return;
|
|
1916
1933
|
let a = n.buffered, o = a.length ? a.end(a.length - 1) : 0;
|
|
1917
|
-
if (i.edge - o >
|
|
1918
|
-
let s =
|
|
1934
|
+
if (i.edge - o > qt * (i.partTarget || .5)) return;
|
|
1935
|
+
let s = Gt(e);
|
|
1919
1936
|
s && t.prefetchHint(s, r);
|
|
1920
1937
|
};
|
|
1921
1938
|
_.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1927,15 +1944,15 @@ var er = class {
|
|
|
1927
1944
|
if (this.prefetch && p) {
|
|
1928
1945
|
let t = this.prefetch;
|
|
1929
1946
|
_.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1930
|
-
let r = n?.frag, i =
|
|
1931
|
-
if (r && t.isActive(i)) for (let e of
|
|
1932
|
-
}), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1947
|
+
let r = n?.frag, i = Ut(r?.type);
|
|
1948
|
+
if (r && t.isActive(i)) for (let e of Wt(_, r)) t.prefetch(e.url, i, e.kind);
|
|
1949
|
+
}), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Ut(n?.frag?.type)));
|
|
1933
1950
|
}
|
|
1934
1951
|
_.on(e.Events.KEY_LOADED, () => {
|
|
1935
1952
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1936
1953
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1937
1954
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.reviewSizeCapHeadroom(), this.releaseStallCap(), this.checkFrameDrops();
|
|
1938
|
-
},
|
|
1955
|
+
}, rn), _.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1939
1956
|
this.renditionSwitches += 1;
|
|
1940
1957
|
let n = this.lastLevelIndex >= 0 ? _.levels[this.lastLevelIndex] : void 0, r = _.levels[t.level];
|
|
1941
1958
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, this.armFrameDropGrace(), l({
|
|
@@ -1996,8 +2013,8 @@ var er = class {
|
|
|
1996
2013
|
let e = this.hls, t = this.sizeCapCover();
|
|
1997
2014
|
if (!e || !t) return null;
|
|
1998
2015
|
let { cover: n, deviceRatio: r } = t, i = this.deps.sizeCapHeadroom, a = i == null || Number.isNaN(i);
|
|
1999
|
-
if (a && r >=
|
|
2000
|
-
if (a) return this.headroomUngated || this.headroomGranted ? J(e.levels, n,
|
|
2016
|
+
if (a && r >= Cn) return n;
|
|
2017
|
+
if (a) return this.headroomUngated || this.headroomGranted ? J(e.levels, n, Sn) : n;
|
|
2001
2018
|
let o = i === Infinity ? e.levels.length : Math.max(0, Math.floor(i));
|
|
2002
2019
|
return J(e.levels, n, o);
|
|
2003
2020
|
}
|
|
@@ -2014,11 +2031,11 @@ var er = class {
|
|
|
2014
2031
|
return;
|
|
2015
2032
|
}
|
|
2016
2033
|
this.capTimer && clearTimeout(this.capTimer);
|
|
2017
|
-
let t = e > this.sizeCapLevel ?
|
|
2034
|
+
let t = e > this.sizeCapLevel ? bn : xn;
|
|
2018
2035
|
this.capTimer = setTimeout(() => {
|
|
2019
2036
|
this.capTimer = null;
|
|
2020
2037
|
let n = this.computeSizeCapTarget();
|
|
2021
|
-
n === e || t ===
|
|
2038
|
+
n === e || t === xn && n != null && n < e ? this.applySizeCap() : this.onMediaResize();
|
|
2022
2039
|
}, t);
|
|
2023
2040
|
}
|
|
2024
2041
|
measureLadder(e) {
|
|
@@ -2045,7 +2062,7 @@ var er = class {
|
|
|
2045
2062
|
}
|
|
2046
2063
|
defaultHeadroomApplies() {
|
|
2047
2064
|
let e = this.deps.sizeCapHeadroom;
|
|
2048
|
-
return e != null && !Number.isNaN(e) || this.headroomUngated ? !1 : Y() <
|
|
2065
|
+
return e != null && !Number.isNaN(e) || this.headroomUngated ? !1 : Y() < Cn;
|
|
2049
2066
|
}
|
|
2050
2067
|
applySizeCapUnlessPending() {
|
|
2051
2068
|
this.capTimer || this.applySizeCap();
|
|
@@ -2054,7 +2071,7 @@ var er = class {
|
|
|
2054
2071
|
if (!this.sizeCapManaged || !this.defaultHeadroomApplies() || e.frag?.type !== "main" || typeof e.frag.level != "number" || typeof document < "u" && document.hidden) return;
|
|
2055
2072
|
let t = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag.duration;
|
|
2056
2073
|
if (typeof t != "number" || !(t > 0)) return;
|
|
2057
|
-
let n =
|
|
2074
|
+
let n = Qn(e)?.loading;
|
|
2058
2075
|
if (!n || !(n.start > 0) || !(n.end >= n.start)) return;
|
|
2059
2076
|
let r = this.hls?.levels?.[e.frag.level]?.bitrate;
|
|
2060
2077
|
if (!(typeof r == "number" && r > 0)) return;
|
|
@@ -2067,7 +2084,7 @@ var er = class {
|
|
|
2067
2084
|
}
|
|
2068
2085
|
onPlaybackStall(e) {
|
|
2069
2086
|
let t = Date.now();
|
|
2070
|
-
this.deps.video.seeking || !this.playingSince || t - this.playingSince <
|
|
2087
|
+
this.deps.video.seeking || !this.playingSince || t - this.playingSince < On || (this.lastStallAt = t, this.stepStallCapDown(t, e), this.headroomGranted && (this.headroomGranted = !1, this.applySizeCapUnlessPending()));
|
|
2071
2088
|
}
|
|
2072
2089
|
stallCapLevel(e) {
|
|
2073
2090
|
if (this.stallCapBitrate == null) return -1;
|
|
@@ -2078,7 +2095,7 @@ var er = class {
|
|
|
2078
2095
|
}
|
|
2079
2096
|
stepStallCapDown(e, t) {
|
|
2080
2097
|
let n = this.hls;
|
|
2081
|
-
if (!n || !this.stallCapEnabled ||
|
|
2098
|
+
if (!n || !this.stallCapEnabled || Mn(n) || !n.autoLevelEnabled || typeof t == "number" && t >= An || this.isLiveEdgeWait(n, t ?? 0)) return;
|
|
2082
2099
|
this.stallCapBitrate != null && (this.stallCapSince = e);
|
|
2083
2100
|
let r = Math.max(n.levels[n.currentLevel]?.bitrate ?? 0, n.levels[n.loadLevel]?.bitrate ?? 0);
|
|
2084
2101
|
if (!(r > 0)) return;
|
|
@@ -2089,7 +2106,7 @@ var er = class {
|
|
|
2089
2106
|
let n = e.latestLevelDetails;
|
|
2090
2107
|
if (!n?.live) return !1;
|
|
2091
2108
|
let r = n.partTarget || n.targetduration;
|
|
2092
|
-
return !(r > 0) || !(n.edge > 0) ? !1 : n.edge - (this.deps.video.currentTime + t) <
|
|
2109
|
+
return !(r > 0) || !(n.edge > 0) ? !1 : n.edge - (this.deps.video.currentTime + t) < jn * r;
|
|
2093
2110
|
}
|
|
2094
2111
|
releaseStallCap() {
|
|
2095
2112
|
let e = this.hls, t = Date.now(), n = this.stallCapTickAt;
|
|
@@ -2098,7 +2115,7 @@ var er = class {
|
|
|
2098
2115
|
n && (this.stallCapSince += t - Math.max(n, this.stallCapSince));
|
|
2099
2116
|
return;
|
|
2100
2117
|
}
|
|
2101
|
-
if (t - this.stallCapSince <
|
|
2118
|
+
if (t - this.stallCapSince < kn) return;
|
|
2102
2119
|
let r = this.stallCapBitrate, i = e.levels.map((e) => e.bitrate).filter((e) => e > r).sort((e, t) => e - t)[0];
|
|
2103
2120
|
this.stallCapBitrate = i ?? null, this.stallCapSince = t, this.pushCap();
|
|
2104
2121
|
}
|
|
@@ -2111,26 +2128,26 @@ var er = class {
|
|
|
2111
2128
|
this.headroomGranted = !1, this.headroomSamples = [];
|
|
2112
2129
|
return;
|
|
2113
2130
|
}
|
|
2114
|
-
this.headroomSamples = this.headroomSamples.filter((t) => t.t >= e -
|
|
2131
|
+
this.headroomSamples = this.headroomSamples.filter((t) => t.t >= e - Un);
|
|
2115
2132
|
let r = this.headroomEarned(n, e);
|
|
2116
|
-
r !== this.headroomGranted && (r || (this.headroomRegrantAt = e +
|
|
2133
|
+
r !== this.headroomGranted && (r || (this.headroomRegrantAt = e + Pn), this.headroomGranted = r, this.applySizeCapUnlessPending());
|
|
2117
2134
|
}
|
|
2118
2135
|
headroomEarned(e, t) {
|
|
2119
|
-
if (t - this.lastStallAt <
|
|
2136
|
+
if (t - this.lastStallAt < Nn || !this.headroomGranted && t < this.headroomRegrantAt || !this.headroomGranted && this.headroomSamples.length < q) return !1;
|
|
2120
2137
|
let n = e.levels, r = this.sizeCapCoverLevel();
|
|
2121
2138
|
if (r == null) return this.headroomGranted;
|
|
2122
|
-
let i = J(n, r,
|
|
2139
|
+
let i = J(n, r, Sn);
|
|
2123
2140
|
if (i === r) return this.headroomGranted;
|
|
2124
|
-
let a = n[i]?.bitrate, o = e.bandwidthEstimate, s = this.headroomGranted ?
|
|
2141
|
+
let a = n[i]?.bitrate, o = e.bandwidthEstimate, s = this.headroomGranted ? Dn : En;
|
|
2125
2142
|
if (!(a > 0) || !(o >= s * a)) return !1;
|
|
2126
2143
|
let c = (e) => K([...e].sort((e, t) => e - t), 90);
|
|
2127
2144
|
if (this.headroomGranted) {
|
|
2128
2145
|
let e = this.headroomSamples.filter((e) => e.bitrate >= a).map((e) => e.ratio);
|
|
2129
|
-
return e.length < q || c(e) <=
|
|
2146
|
+
return e.length < q || c(e) <= Tn;
|
|
2130
2147
|
}
|
|
2131
2148
|
let l = [];
|
|
2132
2149
|
for (let e of this.headroomSamples) e.bitrate < a && l.push(e.ratio * (a / e.bitrate));
|
|
2133
|
-
return l.length >= q && c(l) <=
|
|
2150
|
+
return l.length >= q && c(l) <= wn;
|
|
2134
2151
|
}
|
|
2135
2152
|
applySizeCap() {
|
|
2136
2153
|
if (!this.sizeCapManaged) return;
|
|
@@ -2205,7 +2222,7 @@ var er = class {
|
|
|
2205
2222
|
let t = e.currentLevel >= 0 ? e.levels[e.currentLevel] : void 0;
|
|
2206
2223
|
t && (n.levelHeight = t.height);
|
|
2207
2224
|
let r = e.autoLevelCapping, i = r >= 0 ? e.levels[r] : void 0;
|
|
2208
|
-
i && i.height > 0 && (n.maxLevelHeight = i.height, !
|
|
2225
|
+
i && i.height > 0 && (n.maxLevelHeight = i.height, !Mn(e) && r === this.pushedCapLevel && this.pushedCapReason && (n.capReason = this.pushedCapReason)), t?.videoCodec && (n.videoCodec = t.videoCodec), t?.audioCodec && (n.audioCodec = t.audioCodec), t && typeof t.bitrate == "number" && (n.renditionBitrateKbps = Math.round(t.bitrate / 1e3)), typeof t?.details?.live == "boolean" && (n.isLive = t.details.live, typeof e.liveSyncPosition == "number" && (n.atLiveEdge = this.deps.video.currentTime >= e.liveSyncPosition - 1.5));
|
|
2209
2226
|
}
|
|
2210
2227
|
return n;
|
|
2211
2228
|
}
|
|
@@ -2233,7 +2250,7 @@ var er = class {
|
|
|
2233
2250
|
return;
|
|
2234
2251
|
}
|
|
2235
2252
|
let e = Date.now() - this.lastAdvanceMs;
|
|
2236
|
-
!this.chaseSuspended && e >
|
|
2253
|
+
!this.chaseSuspended && e > on && this.suspendChasing(), e > nn && this.emitEnded("stalled");
|
|
2237
2254
|
}
|
|
2238
2255
|
resetStarvationWindow() {
|
|
2239
2256
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -2248,7 +2265,7 @@ var er = class {
|
|
|
2248
2265
|
this.resetStarvationWindow();
|
|
2249
2266
|
return;
|
|
2250
2267
|
}
|
|
2251
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
2268
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < on, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > pn, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = R(t), c = o - s, l = c !== this.starvedFrames;
|
|
2252
2269
|
if (this.starvedFrames = c, !a || l) {
|
|
2253
2270
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
2254
2271
|
return;
|
|
@@ -2257,12 +2274,12 @@ var er = class {
|
|
|
2257
2274
|
this.resetStarvationWindow();
|
|
2258
2275
|
return;
|
|
2259
2276
|
}
|
|
2260
|
-
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length >
|
|
2277
|
+
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > vn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= gn && (this.clearKick(), this.starvationRebuilds < _n)) {
|
|
2261
2278
|
this.starvationRebuilds += 1, this.resetStarvationWindow(), this.clearRecoveryReset(), console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
|
|
2262
2279
|
return;
|
|
2263
2280
|
}
|
|
2264
|
-
let u = i && this.starvedTicks >=
|
|
2265
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
2281
|
+
let u = i && this.starvedTicks >= mn, d = !i && this.deadTicks >= vn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= yn;
|
|
2282
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= hn))) {
|
|
2266
2283
|
this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, this.kickKind = d ? "dead" : "quiet", this.clearRecoveryReset(), console.warn(d ? "havik-player: video starved while hls.js keeps loading media it never plays (dead pipeline at the live edge) — restarting the load" : "havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
|
|
2267
2284
|
try {
|
|
2268
2285
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -2277,7 +2294,7 @@ var er = class {
|
|
|
2277
2294
|
let t = e.latency, n = e.targetLatency;
|
|
2278
2295
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
2279
2296
|
let r = t - n;
|
|
2280
|
-
!this.catchUpEngaged && r >
|
|
2297
|
+
!this.catchUpEngaged && r > sn ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= sn && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
2281
2298
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
2282
2299
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
2283
2300
|
}
|
|
@@ -2290,7 +2307,7 @@ var er = class {
|
|
|
2290
2307
|
}), n < 0 ? 0 : n;
|
|
2291
2308
|
}
|
|
2292
2309
|
armFrameDropGrace() {
|
|
2293
|
-
this.fpsGraceTicks > 0 || (this.fpsGraceTicks =
|
|
2310
|
+
this.fpsGraceTicks > 0 || (this.fpsGraceTicks = Rn, this.fpsBadTicks = 0);
|
|
2294
2311
|
}
|
|
2295
2312
|
resetFrameDropWindow() {
|
|
2296
2313
|
this.fpsLastFrames = -1, this.fpsLastDropped = -1, this.fpsBadTicks = 0;
|
|
@@ -2302,7 +2319,7 @@ var er = class {
|
|
|
2302
2319
|
return;
|
|
2303
2320
|
}
|
|
2304
2321
|
let { totalFrames: n, dropped: r } = R(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
2305
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
2322
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < In || o < 0) {
|
|
2306
2323
|
this.fpsBadTicks = 0;
|
|
2307
2324
|
return;
|
|
2308
2325
|
}
|
|
@@ -2310,11 +2327,11 @@ var er = class {
|
|
|
2310
2327
|
--this.fpsGraceTicks, this.fpsBadTicks = 0;
|
|
2311
2328
|
return;
|
|
2312
2329
|
}
|
|
2313
|
-
if (o <=
|
|
2330
|
+
if (o <= Fn * a) {
|
|
2314
2331
|
this.fpsBadTicks = 0;
|
|
2315
2332
|
return;
|
|
2316
2333
|
}
|
|
2317
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
2334
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < Ln) return;
|
|
2318
2335
|
this.fpsBadTicks = 0;
|
|
2319
2336
|
let s = e.levels, c = s[e.currentLevel];
|
|
2320
2337
|
if (!c) return;
|
|
@@ -2331,22 +2348,22 @@ var er = class {
|
|
|
2331
2348
|
return;
|
|
2332
2349
|
}
|
|
2333
2350
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
2334
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
2351
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(un, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
2335
2352
|
this.resetChaseWindow();
|
|
2336
2353
|
return;
|
|
2337
2354
|
}
|
|
2338
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
2355
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= ln) {
|
|
2339
2356
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
2340
2357
|
return;
|
|
2341
2358
|
}
|
|
2342
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
2359
|
+
if (this.chaseTicks += 1, this.chaseTicks < cn) return;
|
|
2343
2360
|
this.resetChaseWindow();
|
|
2344
2361
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2345
2362
|
if (!(a > 1)) return;
|
|
2346
2363
|
let o = e.targetLatency;
|
|
2347
2364
|
if (typeof o != "number" || !(o > 0)) return;
|
|
2348
2365
|
let s = Math.min(n, a - 1);
|
|
2349
|
-
s < o +
|
|
2366
|
+
s < o + dn || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s, this.deps.emit({
|
|
2350
2367
|
type: "livetargetchange",
|
|
2351
2368
|
change: {
|
|
2352
2369
|
targetSeconds: s,
|
|
@@ -2363,13 +2380,13 @@ var er = class {
|
|
|
2363
2380
|
if (!this.holdBackEnabled || this.holdBackPriorChecked || !e || (this.holdBackPriorChecked = !0, this.holdBackApplied > 0 || this.holdBackStepCount > 0)) return;
|
|
2364
2381
|
let t = e.targetLatency;
|
|
2365
2382
|
if (this.holdBackBase < 0 && typeof t == "number" && t > 0 && (this.holdBackBase = t), this.holdBackBase < 0) return;
|
|
2366
|
-
let n =
|
|
2367
|
-
if (!(n >=
|
|
2383
|
+
let n = $n();
|
|
2384
|
+
if (!(n >= Zn)) return;
|
|
2368
2385
|
let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase + X);
|
|
2369
2386
|
i > r && (this.holdBackStepCount = 1, this.moveHoldBack(e, r, i, "connection-rtt", `connection rtt ${n} ms`));
|
|
2370
2387
|
}
|
|
2371
2388
|
holdBackCeiling(e) {
|
|
2372
|
-
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t :
|
|
2389
|
+
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : Xn, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2373
2390
|
return r > 1 ? Math.min(n, r - 1) : n;
|
|
2374
2391
|
}
|
|
2375
2392
|
sampleHoldBack(e) {
|
|
@@ -2378,7 +2395,7 @@ var er = class {
|
|
|
2378
2395
|
if (t !== "main" && t !== "audio") return;
|
|
2379
2396
|
let n = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag?.duration;
|
|
2380
2397
|
if (typeof n != "number" || !(n > 0)) return;
|
|
2381
|
-
let r =
|
|
2398
|
+
let r = Qn(e)?.loading;
|
|
2382
2399
|
if (!r || !(r.start > 0) || !(r.end > 0)) return;
|
|
2383
2400
|
let i = r.first > r.start ? r.first : r.end, a = Math.max(0, i - r.start) / (n * 1e3);
|
|
2384
2401
|
this.holdBackSamples.push({
|
|
@@ -2393,20 +2410,20 @@ var er = class {
|
|
|
2393
2410
|
this.holdBackSlowTicks = 0, this.holdBackFastSince = 0, this.holdBackSamples = [];
|
|
2394
2411
|
return;
|
|
2395
2412
|
}
|
|
2396
|
-
let t = Date.now(), n = t -
|
|
2413
|
+
let t = Date.now(), n = t - Un, r = this.holdBackSamples, i = 0;
|
|
2397
2414
|
for (; i < r.length && r[i].t < n;) i += 1;
|
|
2398
2415
|
i > 0 && r.splice(0, i);
|
|
2399
2416
|
let a = e.targetLatency;
|
|
2400
2417
|
if (typeof a != "number" || !(a > 0)) return;
|
|
2401
2418
|
this.holdBackBase < 0 && (this.holdBackBase = a);
|
|
2402
2419
|
let o = this.holdBackBase, s = this.holdBackCeiling(e);
|
|
2403
|
-
if (r.length <
|
|
2420
|
+
if (r.length < Wn) {
|
|
2404
2421
|
this.holdBackSlowTicks = 0;
|
|
2405
2422
|
return;
|
|
2406
2423
|
}
|
|
2407
2424
|
let c = r.map((e) => e.ratio).sort((e, t) => e - t), l = K(c, 95), u = K(c, 50), d = Math.round(l * 1e3);
|
|
2408
|
-
if (l >=
|
|
2409
|
-
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks <
|
|
2425
|
+
if (l >= Gn && u >= Kn) {
|
|
2426
|
+
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < Jn) return;
|
|
2410
2427
|
this.holdBackSlowTicks = 0;
|
|
2411
2428
|
let t = Math.ceil((s - o) / X), n = Math.ceil((a - o) / X - 1e-9);
|
|
2412
2429
|
if (n > this.holdBackStepCount && (this.holdBackStepCount = n), this.holdBackStepCount >= t) return;
|
|
@@ -2416,7 +2433,7 @@ var er = class {
|
|
|
2416
2433
|
this.moveHoldBack(e, a, r, "slow-fetches", `part fetches slow (first byte p50 ${Math.round(u * 1e3)} / p95 ${d} ms per 1 s of media)`);
|
|
2417
2434
|
return;
|
|
2418
2435
|
}
|
|
2419
|
-
if (this.holdBackSlowTicks = 0, l >=
|
|
2436
|
+
if (this.holdBackSlowTicks = 0, l >= qn) {
|
|
2420
2437
|
this.holdBackFastSince = 0;
|
|
2421
2438
|
return;
|
|
2422
2439
|
}
|
|
@@ -2424,7 +2441,7 @@ var er = class {
|
|
|
2424
2441
|
this.holdBackFastSince = t;
|
|
2425
2442
|
return;
|
|
2426
2443
|
}
|
|
2427
|
-
if (t - this.holdBackFastSince <
|
|
2444
|
+
if (t - this.holdBackFastSince < Yn || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
|
|
2428
2445
|
--this.holdBackStepCount;
|
|
2429
2446
|
let f = Math.max(o, o + this.holdBackStepCount * X);
|
|
2430
2447
|
f >= a || this.moveHoldBack(e, a, f, "fast-fetches", `part fetches fast again (p95 first byte ${d} ms per 1 s of media)`);
|
|
@@ -2467,12 +2484,12 @@ var er = class {
|
|
|
2467
2484
|
} catch {}
|
|
2468
2485
|
}
|
|
2469
2486
|
startEstimate() {
|
|
2470
|
-
return this.deps.rememberBandwidth === !1 ?
|
|
2487
|
+
return this.deps.rememberBandwidth === !1 ? Jt : Be() ?? Jt;
|
|
2471
2488
|
}
|
|
2472
2489
|
maybeRememberBandwidth(e) {
|
|
2473
|
-
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded <
|
|
2490
|
+
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Yt) return;
|
|
2474
2491
|
let t = Date.now();
|
|
2475
|
-
if (!e && t - this.bwSavedAt <
|
|
2492
|
+
if (!e && t - this.bwSavedAt < Xt) return;
|
|
2476
2493
|
let n = this.hls?.bandwidthEstimate;
|
|
2477
2494
|
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Ve(n));
|
|
2478
2495
|
}
|
|
@@ -2492,7 +2509,7 @@ var er = class {
|
|
|
2492
2509
|
scheduleLicenseRetry(t) {
|
|
2493
2510
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
2494
2511
|
let n = t.response?.code ?? 0;
|
|
2495
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
2512
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= $t) return !1;
|
|
2496
2513
|
this.licenseRecoveries += 1;
|
|
2497
2514
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
2498
2515
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -2528,7 +2545,7 @@ var er = class {
|
|
|
2528
2545
|
this.offlineHold = !0, this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null);
|
|
2529
2546
|
return;
|
|
2530
2547
|
}
|
|
2531
|
-
if (this.networkRecoveries <
|
|
2548
|
+
if (this.networkRecoveries < Qt) {
|
|
2532
2549
|
this.networkRecoveries += 1;
|
|
2533
2550
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
2534
2551
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -2545,7 +2562,7 @@ var er = class {
|
|
|
2545
2562
|
return;
|
|
2546
2563
|
}
|
|
2547
2564
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
2548
|
-
if (this.mediaRecoveries <
|
|
2565
|
+
if (this.mediaRecoveries < Zt) {
|
|
2549
2566
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
2550
2567
|
return;
|
|
2551
2568
|
}
|
|
@@ -2566,18 +2583,18 @@ var er = class {
|
|
|
2566
2583
|
}
|
|
2567
2584
|
}
|
|
2568
2585
|
toError(t, r = "PLAYBACK") {
|
|
2569
|
-
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(
|
|
2586
|
+
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(Pt(t.networkDetails)) : void 0;
|
|
2570
2587
|
return new n(r === "DRM" ? a(o, l) : r === "NETWORK" && o === 0 ? "NETWORK" : o === 401 ? "UNAUTHORIZED" : o === 403 ? "FORBIDDEN" : "INTERNAL", o, `${r} error: ${s}${c ? ` (${c})` : ""}`, l ? { serverCode: l } : void 0);
|
|
2571
2588
|
}
|
|
2572
|
-
},
|
|
2589
|
+
}, rr = 15e3, ir = 6e5, ar = 3e5, or = 100, Z = 1, sr = 1e3, cr = 3e4, lr = 1e3, ur = {
|
|
2573
2590
|
inline: "PRESENTATION_INLINE",
|
|
2574
2591
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2575
2592
|
pip: "PRESENTATION_PIP"
|
|
2576
|
-
},
|
|
2593
|
+
}, dr = {
|
|
2577
2594
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2578
2595
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2579
2596
|
none: "KEY_SYSTEM_NONE"
|
|
2580
|
-
},
|
|
2597
|
+
}, fr = /* @__PURE__ */ new Set([
|
|
2581
2598
|
"INVALID_URN",
|
|
2582
2599
|
"NOT_FOUND",
|
|
2583
2600
|
"GEO_DENIED",
|
|
@@ -2588,7 +2605,7 @@ var er = class {
|
|
|
2588
2605
|
"FORBIDDEN",
|
|
2589
2606
|
"RATE_LIMITED",
|
|
2590
2607
|
"TIMEOUT"
|
|
2591
|
-
]),
|
|
2608
|
+
]), pr = {
|
|
2592
2609
|
idle: "PLAYER_STATE_IDLE",
|
|
2593
2610
|
waiting: "PLAYER_STATE_WAITING",
|
|
2594
2611
|
loading: "PLAYER_STATE_LOADING",
|
|
@@ -2598,7 +2615,7 @@ var er = class {
|
|
|
2598
2615
|
ended: "PLAYER_STATE_ENDED",
|
|
2599
2616
|
error: "PLAYER_STATE_ERROR"
|
|
2600
2617
|
};
|
|
2601
|
-
function
|
|
2618
|
+
function mr(e) {
|
|
2602
2619
|
try {
|
|
2603
2620
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2604
2621
|
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);
|
|
@@ -2606,8 +2623,8 @@ function fr(e) {
|
|
|
2606
2623
|
return;
|
|
2607
2624
|
}
|
|
2608
2625
|
}
|
|
2609
|
-
var
|
|
2610
|
-
function
|
|
2626
|
+
var hr = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), gr = /* @__PURE__ */ new Set(), _r = /* @__PURE__ */ new Set(), vr = /* @__PURE__ */ new Set(), yr = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2627
|
+
function br(e) {
|
|
2611
2628
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2612
2629
|
let t;
|
|
2613
2630
|
try {
|
|
@@ -2616,19 +2633,19 @@ function vr(e) {
|
|
|
2616
2633
|
} catch {
|
|
2617
2634
|
return;
|
|
2618
2635
|
}
|
|
2619
|
-
if (
|
|
2620
|
-
|
|
2621
|
-
for (let e of
|
|
2636
|
+
if (gr.has(t) && !_r.has(t)) {
|
|
2637
|
+
_r.add(t), _(yr(new URL(t).origin));
|
|
2638
|
+
for (let e of vr) e.noteCspBlocked();
|
|
2622
2639
|
}
|
|
2623
2640
|
}
|
|
2624
|
-
function
|
|
2641
|
+
function xr(e, t) {
|
|
2625
2642
|
return _(t, e), { disabledReason: t };
|
|
2626
2643
|
}
|
|
2627
|
-
function
|
|
2628
|
-
if (n) return t && !
|
|
2644
|
+
function Sr(e, t, n) {
|
|
2645
|
+
if (n) return t && !hr(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2629
2646
|
if (t) return { endpoint: t };
|
|
2630
|
-
if (t !== void 0) return
|
|
2631
|
-
let r =
|
|
2647
|
+
if (t !== void 0) return xr("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).");
|
|
2648
|
+
let r = mr(e);
|
|
2632
2649
|
if (r) return { endpoint: r };
|
|
2633
2650
|
let i;
|
|
2634
2651
|
try {
|
|
@@ -2636,9 +2653,9 @@ function br(e, t, n) {
|
|
|
2636
2653
|
} catch {
|
|
2637
2654
|
i = e;
|
|
2638
2655
|
}
|
|
2639
|
-
return
|
|
2656
|
+
return xr(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).`);
|
|
2640
2657
|
}
|
|
2641
|
-
var
|
|
2658
|
+
var Cr = class {
|
|
2642
2659
|
opts;
|
|
2643
2660
|
url;
|
|
2644
2661
|
cspKey;
|
|
@@ -2720,8 +2737,8 @@ var xr = class {
|
|
|
2720
2737
|
constructor(e) {
|
|
2721
2738
|
this.opts = {
|
|
2722
2739
|
...e,
|
|
2723
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2724
|
-
idleMs: e.idleMs ??
|
|
2740
|
+
heartbeatMs: e.heartbeatMs ?? rr,
|
|
2741
|
+
idleMs: e.idleMs ?? ir
|
|
2725
2742
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2726
2743
|
try {
|
|
2727
2744
|
let e = new URL(this.url);
|
|
@@ -2738,11 +2755,11 @@ var xr = class {
|
|
|
2738
2755
|
sdkVersion: this.opts.sdkVersion,
|
|
2739
2756
|
...this.opts.environment
|
|
2740
2757
|
};
|
|
2741
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2758
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), sr), 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 && gr.add(this.cspKey), document.addEventListener("securitypolicyviolation", br), vr.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2742
2759
|
}
|
|
2743
2760
|
checkSuspension(e) {
|
|
2744
2761
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2745
|
-
let t = Math.max(this.opts.idleMs,
|
|
2762
|
+
let t = Math.max(this.opts.idleMs, ar);
|
|
2746
2763
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2747
2764
|
}
|
|
2748
2765
|
syncIdle(e) {
|
|
@@ -2763,14 +2780,14 @@ var xr = class {
|
|
|
2763
2780
|
} else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
|
|
2764
2781
|
this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
|
|
2765
2782
|
let a = {
|
|
2766
|
-
fromState:
|
|
2767
|
-
toState:
|
|
2768
|
-
presentation:
|
|
2783
|
+
fromState: pr[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2784
|
+
toState: pr[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2785
|
+
presentation: ur[this.presentation]
|
|
2769
2786
|
}, o = this.causeOf(e, t, i);
|
|
2770
2787
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2771
2788
|
}
|
|
2772
2789
|
seekInduced(e) {
|
|
2773
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2790
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < lr;
|
|
2774
2791
|
}
|
|
2775
2792
|
causeOf(e, t, n) {
|
|
2776
2793
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2844,7 +2861,7 @@ var xr = class {
|
|
|
2844
2861
|
let r = n ?? "";
|
|
2845
2862
|
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";
|
|
2846
2863
|
if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
|
|
2847
|
-
if (
|
|
2864
|
+
if (fr.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2848
2865
|
let i = t ?? "";
|
|
2849
2866
|
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";
|
|
2850
2867
|
}
|
|
@@ -2876,7 +2893,7 @@ var xr = class {
|
|
|
2876
2893
|
let l = t.droppedFrames ?? 0;
|
|
2877
2894
|
l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
|
|
2878
2895
|
let u = t.renditionSwitches ?? 0;
|
|
2879
|
-
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 =
|
|
2896
|
+
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 = pr[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
|
|
2880
2897
|
let d = this.mutedTotalMs;
|
|
2881
2898
|
this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
|
|
2882
2899
|
let f = t.upshifts ?? 0;
|
|
@@ -2898,13 +2915,13 @@ var xr = class {
|
|
|
2898
2915
|
maybeEmitMediaInfo(e) {
|
|
2899
2916
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2900
2917
|
let t = {};
|
|
2901
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2918
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = dr[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);
|
|
2902
2919
|
let n = JSON.stringify(t);
|
|
2903
2920
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2904
2921
|
}
|
|
2905
2922
|
end(e, t) {
|
|
2906
2923
|
if (this.endedFlag) return;
|
|
2907
|
-
this.endedFlag = !0,
|
|
2924
|
+
this.endedFlag = !0, vr.delete(this);
|
|
2908
2925
|
let n = t ?? this.now();
|
|
2909
2926
|
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));
|
|
2910
2927
|
let r = this.safeSample();
|
|
@@ -2918,7 +2935,7 @@ var xr = class {
|
|
|
2918
2935
|
let c = r?.positionMs ?? 0;
|
|
2919
2936
|
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));
|
|
2920
2937
|
let l = e !== "END_REASON_ENDED";
|
|
2921
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2938
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= cr && (i.abandonAfterStallMs = Math.max(Z, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= cr && (i.abandonAfterErrorMs = Math.max(Z, 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);
|
|
2922
2939
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2923
2940
|
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");
|
|
2924
2941
|
}
|
|
@@ -2938,13 +2955,13 @@ var xr = class {
|
|
|
2938
2955
|
};
|
|
2939
2956
|
}
|
|
2940
2957
|
noteCspBlocked() {
|
|
2941
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2958
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(yr(new URL(this.url).origin)));
|
|
2942
2959
|
}
|
|
2943
2960
|
cspBlocked() {
|
|
2944
|
-
return !!this.cspKey &&
|
|
2961
|
+
return !!this.cspKey && _r.has(this.cspKey);
|
|
2945
2962
|
}
|
|
2946
2963
|
enqueue(e) {
|
|
2947
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2964
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > or;) {
|
|
2948
2965
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2949
2966
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2950
2967
|
}
|
|
@@ -2971,7 +2988,7 @@ var xr = class {
|
|
|
2971
2988
|
};
|
|
2972
2989
|
//#endregion
|
|
2973
2990
|
//#region src/core/environment.ts
|
|
2974
|
-
function
|
|
2991
|
+
function wr() {
|
|
2975
2992
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2976
2993
|
let e;
|
|
2977
2994
|
try {
|
|
@@ -2996,14 +3013,14 @@ function Sr() {
|
|
|
2996
3013
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2997
3014
|
};
|
|
2998
3015
|
}
|
|
2999
|
-
function
|
|
3016
|
+
function Tr() {
|
|
3000
3017
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
3001
3018
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
3002
3019
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
3003
3020
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
3004
3021
|
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";
|
|
3005
3022
|
}
|
|
3006
|
-
function
|
|
3023
|
+
function Er() {
|
|
3007
3024
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
3008
3025
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
3009
3026
|
let t = {
|
|
@@ -3022,17 +3039,17 @@ function wr() {
|
|
|
3022
3039
|
}
|
|
3023
3040
|
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;
|
|
3024
3041
|
}
|
|
3025
|
-
function
|
|
3026
|
-
let t =
|
|
3027
|
-
deviceClass:
|
|
3042
|
+
function Dr(e) {
|
|
3043
|
+
let t = wr(), n = {
|
|
3044
|
+
deviceClass: Tr(),
|
|
3028
3045
|
integration: t.integration,
|
|
3029
|
-
...
|
|
3046
|
+
...Er()
|
|
3030
3047
|
};
|
|
3031
3048
|
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);
|
|
3032
3049
|
let r = e.getBoundingClientRect?.();
|
|
3033
3050
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
3034
3051
|
}
|
|
3035
|
-
async function
|
|
3052
|
+
async function Or() {
|
|
3036
3053
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
3037
3054
|
if (!e?.getHighEntropyValues) return {};
|
|
3038
3055
|
try {
|
|
@@ -3044,7 +3061,7 @@ async function Er() {
|
|
|
3044
3061
|
}
|
|
3045
3062
|
//#endregion
|
|
3046
3063
|
//#region src/core/version.ts
|
|
3047
|
-
var
|
|
3064
|
+
var kr = "2.27.2", Ar = {
|
|
3048
3065
|
accent: "#E1B600",
|
|
3049
3066
|
accentText: "#1B1C23",
|
|
3050
3067
|
background: "#0e0f13",
|
|
@@ -3055,7 +3072,7 @@ var Dr = "2.27.0", Or = {
|
|
|
3055
3072
|
border: "rgba(255, 255, 255, 0.1)",
|
|
3056
3073
|
radius: "8px",
|
|
3057
3074
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
3058
|
-
},
|
|
3075
|
+
}, jr = {
|
|
3059
3076
|
accent: "--havik-accent",
|
|
3060
3077
|
accentText: "--havik-accent-text",
|
|
3061
3078
|
background: "--havik-bg",
|
|
@@ -3067,26 +3084,26 @@ var Dr = "2.27.0", Or = {
|
|
|
3067
3084
|
radius: "--havik-radius",
|
|
3068
3085
|
fontFamily: "--havik-font"
|
|
3069
3086
|
};
|
|
3070
|
-
function
|
|
3087
|
+
function Mr(e, t) {
|
|
3071
3088
|
let n = {
|
|
3072
|
-
...
|
|
3089
|
+
...Ar,
|
|
3073
3090
|
...t
|
|
3074
3091
|
};
|
|
3075
|
-
for (let t of Object.keys(
|
|
3092
|
+
for (let t of Object.keys(jr)) e.style.setProperty(jr[t], n[t]);
|
|
3076
3093
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
3077
3094
|
}
|
|
3078
3095
|
//#endregion
|
|
3079
3096
|
//#region src/ui/styles.ts
|
|
3080
|
-
var
|
|
3081
|
-
function
|
|
3082
|
-
let n = e.querySelector(`style#${
|
|
3083
|
-
if (n && (!t ||
|
|
3097
|
+
var Nr = "havik-player-styles", Pr = "\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", Fr = /* @__PURE__ */ new WeakMap();
|
|
3098
|
+
function Ir(e = document, t) {
|
|
3099
|
+
let n = e.querySelector(`style#${Nr}`);
|
|
3100
|
+
if (n && (!t || Fr.get(n) === t)) return;
|
|
3084
3101
|
let r = e.createElement("style");
|
|
3085
|
-
r.id =
|
|
3102
|
+
r.id = Nr, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Pr, Fr.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
3086
3103
|
}
|
|
3087
3104
|
//#endregion
|
|
3088
3105
|
//#region src/ui/icons.ts
|
|
3089
|
-
var
|
|
3106
|
+
var Lr = {
|
|
3090
3107
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
3091
3108
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
3092
3109
|
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\"/>",
|
|
@@ -3100,11 +3117,11 @@ var Fr = {
|
|
|
3100
3117
|
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\"/>"
|
|
3101
3118
|
};
|
|
3102
3119
|
function Q(e) {
|
|
3103
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
3120
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Lr[e]}</svg>`;
|
|
3104
3121
|
}
|
|
3105
3122
|
//#endregion
|
|
3106
3123
|
//#region src/ui/controls.ts
|
|
3107
|
-
var
|
|
3124
|
+
var Rr = 3e3, zr = 250, Br = /* @__PURE__ */ new Set([
|
|
3108
3125
|
"GONE",
|
|
3109
3126
|
"NOT_FOUND",
|
|
3110
3127
|
"GEO_DENIED",
|
|
@@ -3112,15 +3129,15 @@ var Ir = 3e3, Lr = 250, Rr = /* @__PURE__ */ new Set([
|
|
|
3112
3129
|
"UNAUTHORIZED",
|
|
3113
3130
|
"DRM_DEVICE_REVOKED"
|
|
3114
3131
|
]);
|
|
3115
|
-
function
|
|
3132
|
+
function Vr(e) {
|
|
3116
3133
|
let t = "This match isn't available in your country";
|
|
3117
3134
|
return e ? `${t} (${e})` : t;
|
|
3118
3135
|
}
|
|
3119
|
-
var
|
|
3120
|
-
function
|
|
3121
|
-
return new
|
|
3136
|
+
var Hr = "This device can't play protected video";
|
|
3137
|
+
function Ur(e) {
|
|
3138
|
+
return new Wr(e);
|
|
3122
3139
|
}
|
|
3123
|
-
var
|
|
3140
|
+
var Wr = class {
|
|
3124
3141
|
root;
|
|
3125
3142
|
video;
|
|
3126
3143
|
player;
|
|
@@ -3169,7 +3186,7 @@ var Hr = class {
|
|
|
3169
3186
|
scrubbing = !1;
|
|
3170
3187
|
offFns = [];
|
|
3171
3188
|
constructor(e) {
|
|
3172
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
3189
|
+
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, this.offlineMessage = e.offlineMessage ?? "No internet connection — waiting to reconnect", Ir(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");
|
|
3173
3190
|
let t = (e, t, n) => {
|
|
3174
3191
|
let r = this.doc.createElement(e);
|
|
3175
3192
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -3255,7 +3272,7 @@ var Hr = class {
|
|
|
3255
3272
|
let t = this.surfaceWasHidden;
|
|
3256
3273
|
this.tapTimer = setTimeout(() => {
|
|
3257
3274
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
3258
|
-
},
|
|
3275
|
+
}, zr);
|
|
3259
3276
|
}
|
|
3260
3277
|
toggleBar(e) {
|
|
3261
3278
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -3282,7 +3299,7 @@ var Hr = class {
|
|
|
3282
3299
|
this.renderStatus(t);
|
|
3283
3300
|
}
|
|
3284
3301
|
statusMessageFor(e) {
|
|
3285
|
-
return e === "ended" ? this.isGone() ? this.endedMessage : this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "offline" ? this.offlineMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ?
|
|
3302
|
+
return e === "ended" ? this.isGone() ? this.endedMessage : this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "offline" ? this.offlineMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? Vr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? Hr : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
|
|
3286
3303
|
}
|
|
3287
3304
|
renderStatus(e) {
|
|
3288
3305
|
let t = this.statusMessageFor(e);
|
|
@@ -3297,7 +3314,7 @@ var Hr = class {
|
|
|
3297
3314
|
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);
|
|
3298
3315
|
} else {
|
|
3299
3316
|
let r = this.doc.createElement("div");
|
|
3300
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
3317
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Br.has(this.lastError.code)) {
|
|
3301
3318
|
let e = this.doc.createElement("button");
|
|
3302
3319
|
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);
|
|
3303
3320
|
}
|
|
@@ -3338,7 +3355,7 @@ var Hr = class {
|
|
|
3338
3355
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
3339
3356
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
3340
3357
|
}
|
|
3341
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
3358
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Gr(this.video.currentTime)} / ${Gr(this.video.duration)}`);
|
|
3342
3359
|
}
|
|
3343
3360
|
syncLive() {
|
|
3344
3361
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.isGone(), r = this.player.state === "ended" || n, i = !t && !this.streamEnded() && !n;
|
|
@@ -3388,17 +3405,17 @@ var Hr = class {
|
|
|
3388
3405
|
renderQualityMenu() {
|
|
3389
3406
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
3390
3407
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
3391
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
3408
|
+
for (let n of e) this.menu.append(this.menuItem(Kr(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
3392
3409
|
}
|
|
3393
3410
|
renderAudioMenu() {
|
|
3394
3411
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
3395
3412
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
3396
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3413
|
+
for (let t of e) this.menu.append(this.menuItem(qr(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
3397
3414
|
}
|
|
3398
3415
|
renderCcMenu() {
|
|
3399
3416
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
3400
3417
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
3401
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3418
|
+
for (let t of e) this.menu.append(this.menuItem(Jr(t), !1, () => this.player.setTextTrack(t.id)));
|
|
3402
3419
|
}
|
|
3403
3420
|
onTracksChanged() {
|
|
3404
3421
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -3503,23 +3520,23 @@ var Hr = class {
|
|
|
3503
3520
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
3504
3521
|
}
|
|
3505
3522
|
};
|
|
3506
|
-
function
|
|
3523
|
+
function Gr(e) {
|
|
3507
3524
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3508
3525
|
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");
|
|
3509
3526
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3510
3527
|
}
|
|
3511
|
-
function
|
|
3528
|
+
function Kr(e) {
|
|
3512
3529
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3513
3530
|
}
|
|
3514
|
-
function
|
|
3531
|
+
function qr(e) {
|
|
3515
3532
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3516
3533
|
}
|
|
3517
|
-
function
|
|
3534
|
+
function Jr(e) {
|
|
3518
3535
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3519
3536
|
}
|
|
3520
3537
|
//#endregion
|
|
3521
3538
|
//#region src/managed/index.ts
|
|
3522
|
-
var
|
|
3539
|
+
var Yr = 6e3, Xr = 45e3, Zr = 2e3, Qr = 3, $r = 5e3, ei = 2e3, ti = 48e4, ni = "keySystemLicenseRequestFailed", ri = /* @__PURE__ */ new Set([
|
|
3523
3540
|
"GONE",
|
|
3524
3541
|
"NOT_FOUND",
|
|
3525
3542
|
"INVALID_URN",
|
|
@@ -3527,27 +3544,27 @@ var qr = 6e3, Jr = 45e3, Yr = 2e3, Xr = 3, Zr = 5e3, Qr = 2e3, $r = 48e4, ei = "
|
|
|
3527
3544
|
"GEO_DENIED",
|
|
3528
3545
|
"DRM_DEVICE_REVOKED"
|
|
3529
3546
|
]);
|
|
3530
|
-
function
|
|
3531
|
-
return !
|
|
3547
|
+
function ii(e) {
|
|
3548
|
+
return !ri.has(e);
|
|
3532
3549
|
}
|
|
3533
|
-
function
|
|
3550
|
+
function ai(e) {
|
|
3534
3551
|
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)})`);
|
|
3535
3552
|
if (e.env !== void 0) return lt(e.env);
|
|
3536
3553
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3537
3554
|
return e.baseUrl;
|
|
3538
3555
|
}
|
|
3539
|
-
async function
|
|
3556
|
+
async function oi(e) {
|
|
3540
3557
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3541
|
-
let t =
|
|
3558
|
+
let t = ai(e);
|
|
3542
3559
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3543
3560
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3544
|
-
let r = new
|
|
3561
|
+
let r = new si({
|
|
3545
3562
|
...e,
|
|
3546
3563
|
baseUrl: t
|
|
3547
3564
|
});
|
|
3548
3565
|
return await r.start(), r;
|
|
3549
3566
|
}
|
|
3550
|
-
var
|
|
3567
|
+
var si = class {
|
|
3551
3568
|
opts;
|
|
3552
3569
|
abort = new AbortController();
|
|
3553
3570
|
listeners = {};
|
|
@@ -3647,7 +3664,7 @@ var ai = class {
|
|
|
3647
3664
|
setTimeout(() => {
|
|
3648
3665
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3649
3666
|
phase: i ? "unavailable" : "tooEarly",
|
|
3650
|
-
retryInMs:
|
|
3667
|
+
retryInMs: Xr,
|
|
3651
3668
|
attempt: 1,
|
|
3652
3669
|
elapsedMs: 0,
|
|
3653
3670
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3686,13 +3703,13 @@ var ai = class {
|
|
|
3686
3703
|
!a && !p() && h();
|
|
3687
3704
|
}, e);
|
|
3688
3705
|
};
|
|
3689
|
-
_(
|
|
3706
|
+
_(Yr), this.armingSub = D({
|
|
3690
3707
|
eventsBaseUrl: t,
|
|
3691
3708
|
matchUrn: this.opts.matchUrn,
|
|
3692
3709
|
credential: this.opts.credential,
|
|
3693
|
-
onAlive: () => _(
|
|
3710
|
+
onAlive: () => _(Xr),
|
|
3694
3711
|
onState: (e) => {
|
|
3695
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3712
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Zr);
|
|
3696
3713
|
},
|
|
3697
3714
|
onError: () => h()
|
|
3698
3715
|
});
|
|
@@ -3715,7 +3732,7 @@ var ai = class {
|
|
|
3715
3732
|
let n = await c(this.opts.credential);
|
|
3716
3733
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3717
3734
|
this.setState("loading");
|
|
3718
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3735
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = vt(this.opts.video, (e) => {
|
|
3719
3736
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3720
3737
|
});
|
|
3721
3738
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3737,19 +3754,19 @@ var ai = class {
|
|
|
3737
3754
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3738
3755
|
let i = e.analytics?.sid;
|
|
3739
3756
|
if (!i) return;
|
|
3740
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3757
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Sr(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3741
3758
|
if (!o) {
|
|
3742
3759
|
s && setTimeout(() => {
|
|
3743
3760
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3744
3761
|
}, 0);
|
|
3745
3762
|
return;
|
|
3746
3763
|
}
|
|
3747
|
-
let c = this.opts.video, l = new
|
|
3764
|
+
let c = this.opts.video, l = new Cr({
|
|
3748
3765
|
endpoint: o,
|
|
3749
3766
|
sid: i,
|
|
3750
3767
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3751
|
-
sdkVersion:
|
|
3752
|
-
environment:
|
|
3768
|
+
sdkVersion: kr,
|
|
3769
|
+
environment: Dr(c),
|
|
3753
3770
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3754
3771
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3755
3772
|
onBlocked: (e) => setTimeout(() => {
|
|
@@ -3770,7 +3787,7 @@ var ai = class {
|
|
|
3770
3787
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3771
3788
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3772
3789
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3773
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3790
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Or().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3774
3791
|
}
|
|
3775
3792
|
currentPresentation() {
|
|
3776
3793
|
let e = this.opts.video;
|
|
@@ -3803,9 +3820,9 @@ var ai = class {
|
|
|
3803
3820
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3804
3821
|
}, o = this.opts.engine ?? "auto";
|
|
3805
3822
|
if (o === "native") return new H(a);
|
|
3806
|
-
if (o === "hls") return new
|
|
3807
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V() || !e.drmEnabled &&
|
|
3808
|
-
if (
|
|
3823
|
+
if (o === "hls") return new nr(a);
|
|
3824
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V() || !e.drmEnabled && At() && B(this.opts.video)) return new H(a);
|
|
3825
|
+
if (Kt()) return new nr(a);
|
|
3809
3826
|
if (B(this.opts.video)) return new H(a);
|
|
3810
3827
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3811
3828
|
}
|
|
@@ -3876,7 +3893,7 @@ var ai = class {
|
|
|
3876
3893
|
a = !0, this.emit("warning", new n(r(o.status), o.status, `live-state events answered HTTP ${o.status} for ${this.opts.matchUrn}: the match is ` + (o.terminal ? "gone, so the subscription stopped" : "not in the catalog (ended and dropped, or not listed yet), so it retries every 5 min") + " — end-of-stream detection falls back to the HLS staleness watchdog."));
|
|
3877
3894
|
return;
|
|
3878
3895
|
}
|
|
3879
|
-
i += 1, i >=
|
|
3896
|
+
i += 1, i >= Qr && (a = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${i} 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.`)));
|
|
3880
3897
|
}
|
|
3881
3898
|
}
|
|
3882
3899
|
});
|
|
@@ -3893,7 +3910,7 @@ var ai = class {
|
|
|
3893
3910
|
}
|
|
3894
3911
|
if (this.emit("online"), this._state !== "error" || !this._lastError) return;
|
|
3895
3912
|
let t = this._lastError.code;
|
|
3896
|
-
|
|
3913
|
+
ii(t) && (t === "NETWORK" || this.failedWhileOffline) && this.retry().catch(() => void 0);
|
|
3897
3914
|
}));
|
|
3898
3915
|
}
|
|
3899
3916
|
watchReturn() {
|
|
@@ -3903,7 +3920,7 @@ var ai = class {
|
|
|
3903
3920
|
return;
|
|
3904
3921
|
}
|
|
3905
3922
|
let e = this.hiddenAtMs;
|
|
3906
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3923
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= $r && this.resyncLiveState();
|
|
3907
3924
|
}, this.onReturnPageShow = (e) => {
|
|
3908
3925
|
e.persisted && this.resyncLiveState();
|
|
3909
3926
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3935,7 +3952,7 @@ var ai = class {
|
|
|
3935
3952
|
scheduleRejoin(e) {
|
|
3936
3953
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3937
3954
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3938
|
-
}, Math.random() *
|
|
3955
|
+
}, Math.random() * Zr));
|
|
3939
3956
|
}
|
|
3940
3957
|
cancelRejoin() {
|
|
3941
3958
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3959,7 +3976,7 @@ var ai = class {
|
|
|
3959
3976
|
}
|
|
3960
3977
|
t.controls = !1;
|
|
3961
3978
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3962
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3979
|
+
r && r.insertBefore(n, t), n.appendChild(t), Mr(n, this.opts.theme), this.container = n, this.controlBar = Ur({
|
|
3963
3980
|
root: n,
|
|
3964
3981
|
video: t,
|
|
3965
3982
|
player: this,
|
|
@@ -3998,7 +4015,7 @@ var ai = class {
|
|
|
3998
4015
|
}
|
|
3999
4016
|
startStats() {
|
|
4000
4017
|
this.stopStats();
|
|
4001
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
4018
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? ei);
|
|
4002
4019
|
this.statsTimer = setInterval(() => {
|
|
4003
4020
|
if (!this.engine) return;
|
|
4004
4021
|
let e = this.engine.getStats();
|
|
@@ -4009,14 +4026,14 @@ var ai = class {
|
|
|
4009
4026
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
4010
4027
|
}
|
|
4011
4028
|
isStaleLicenseDenial(e) {
|
|
4012
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
4029
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== ni || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : W(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
4013
4030
|
}
|
|
4014
4031
|
scheduleLicenseRefresh() {
|
|
4015
4032
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
4016
4033
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
4017
4034
|
document.visibilityState !== "visible" || this.destroyed || W(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
4018
4035
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
4019
|
-
let e = this.opts.licenseRefreshMs ??
|
|
4036
|
+
let e = this.opts.licenseRefreshMs ?? ti;
|
|
4020
4037
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
4021
4038
|
}
|
|
4022
4039
|
stopRefresh() {
|
|
@@ -4186,7 +4203,7 @@ function $(e) {
|
|
|
4186
4203
|
}
|
|
4187
4204
|
//#endregion
|
|
4188
4205
|
//#region src/embed/host.ts
|
|
4189
|
-
function
|
|
4206
|
+
function ci(e) {
|
|
4190
4207
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
4191
4208
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
4192
4209
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -4245,15 +4262,15 @@ function oi(e) {
|
|
|
4245
4262
|
}
|
|
4246
4263
|
//#endregion
|
|
4247
4264
|
//#region src/embed/page.ts
|
|
4248
|
-
var
|
|
4249
|
-
function
|
|
4265
|
+
var li = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
4266
|
+
function ui(e) {
|
|
4250
4267
|
if (typeof e == "boolean") return e;
|
|
4251
4268
|
if (typeof e == "object" && e) {
|
|
4252
4269
|
let t = e.endpoint;
|
|
4253
4270
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
4254
4271
|
}
|
|
4255
4272
|
}
|
|
4256
|
-
function
|
|
4273
|
+
function di() {
|
|
4257
4274
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
4258
4275
|
if (e) return {
|
|
4259
4276
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -4263,7 +4280,7 @@ function li() {
|
|
|
4263
4280
|
autoplay: e.autoplay ?? !0,
|
|
4264
4281
|
muted: e.muted ?? !0,
|
|
4265
4282
|
waitForLive: e.waitForLive ?? !0,
|
|
4266
|
-
analytics:
|
|
4283
|
+
analytics: ui(e.analytics)
|
|
4267
4284
|
};
|
|
4268
4285
|
let t = new URLSearchParams(location.search);
|
|
4269
4286
|
return {
|
|
@@ -4276,9 +4293,9 @@ function li() {
|
|
|
4276
4293
|
waitForLive: !0
|
|
4277
4294
|
};
|
|
4278
4295
|
}
|
|
4279
|
-
async function
|
|
4280
|
-
let e =
|
|
4281
|
-
|
|
4296
|
+
async function fi() {
|
|
4297
|
+
let e = di();
|
|
4298
|
+
mi();
|
|
4282
4299
|
let t = document.createElement("video");
|
|
4283
4300
|
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);
|
|
4284
4301
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -4334,12 +4351,12 @@ async function ui() {
|
|
|
4334
4351
|
message: e.message,
|
|
4335
4352
|
...e.country === void 0 ? {} : { country: e.country }
|
|
4336
4353
|
})), e.on("autoplayblocked", () => {
|
|
4337
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
4354
|
+
i({ type: "oddin:autoplayblocked" }), pi(t, e);
|
|
4338
4355
|
});
|
|
4339
4356
|
}, s = async (r) => {
|
|
4340
4357
|
a?.destroy(), a = null;
|
|
4341
4358
|
try {
|
|
4342
|
-
let n = await
|
|
4359
|
+
let n = await oi({
|
|
4343
4360
|
video: t,
|
|
4344
4361
|
baseUrl: e.baseUrl,
|
|
4345
4362
|
matchUrn: r,
|
|
@@ -4402,7 +4419,7 @@ async function ui() {
|
|
|
4402
4419
|
a?.retry();
|
|
4403
4420
|
break;
|
|
4404
4421
|
case "oddin:load":
|
|
4405
|
-
typeof e.matchUrn == "string" &&
|
|
4422
|
+
typeof e.matchUrn == "string" && li.test(e.matchUrn) && s(e.matchUrn);
|
|
4406
4423
|
break;
|
|
4407
4424
|
case "oddin:destroy": c();
|
|
4408
4425
|
}
|
|
@@ -4414,18 +4431,18 @@ async function ui() {
|
|
|
4414
4431
|
protocol: 1
|
|
4415
4432
|
});
|
|
4416
4433
|
}
|
|
4417
|
-
function
|
|
4434
|
+
function pi(e, t) {
|
|
4418
4435
|
if (document.getElementById("havik-tap")) return;
|
|
4419
4436
|
let n = document.createElement("button");
|
|
4420
4437
|
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", () => {
|
|
4421
4438
|
n.remove(), t.play();
|
|
4422
4439
|
}), document.body.appendChild(n);
|
|
4423
4440
|
}
|
|
4424
|
-
function
|
|
4441
|
+
function mi() {
|
|
4425
4442
|
let e = document.createElement("style");
|
|
4426
4443
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
4427
4444
|
}
|
|
4428
4445
|
//#endregion
|
|
4429
|
-
export { E as LiveStateHttpError,
|
|
4446
|
+
export { E as LiveStateHttpError, Ar as ODDIN_THEME, n as PlaybackError, Mr as applyTheme, lt as baseUrlForEnv, fi as bootEmbed, ke as clearDeviceId, He as clearRememberedBandwidth, oi as createPlayer, O as deriveEventsBaseUrl, at as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, Oe as getDeviceId, st as isLowLatencyManifest, $ as isOddinMessage, je as licenseRequestHeaders, ci as mountEmbed, fe as pollToLive, y as resolveStream, D as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
|
|
4430
4447
|
|
|
4431
4448
|
//# sourceMappingURL=index.js.map
|