@oddin-gg/havik-player 2.26.0 → 2.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/havik-player.global.js +2 -2
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -4
- package/dist/index.d.ts +23 -4
- package/dist/index.js +205 -161
- package/dist/index.js.map +1 -1
- package/docs/API.md +11 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1574,7 +1574,12 @@ function K(e, t) {
|
|
|
1574
1574
|
function Wt() {
|
|
1575
1575
|
return e.isSupported();
|
|
1576
1576
|
}
|
|
1577
|
-
var Gt = 3, Kt = 1e6, qt = 20, Jt = 1e4, Yt = 3, Xt = 5, Zt = 3, Qt = 1e4, $t = 3e4, en = 12e3, tn = 3e3, nn = .02, rn = 6e3, an = .5, on = 3, sn = .5, cn = 1.1, ln = .25, un = 5e3, dn = 4e3, fn = 2, pn = 5, mn = 2, hn = 2, gn = 4, _n = 4, vn = 2e3, yn = 3e4, bn = 1, xn = 2, Sn = .5, Cn = .6, wn = 2, Tn = 1.5, En = 1e4,
|
|
1577
|
+
var Gt = 3, Kt = 1e6, qt = 20, Jt = 1e4, Yt = 3, Xt = 5, Zt = 3, Qt = 1e4, $t = 3e4, en = 12e3, tn = 3e3, nn = .02, rn = 6e3, an = .5, on = 3, sn = .5, cn = 1.1, ln = .25, un = 5e3, dn = 4e3, fn = 2, pn = 5, mn = 2, hn = 2, gn = 4, _n = 4, vn = 2e3, yn = 3e4, bn = 1, xn = 2, Sn = .5, Cn = .6, wn = 2, Tn = 1.5, En = 1e4, Dn = 18e4, On = .5, kn = 2;
|
|
1578
|
+
function An(e) {
|
|
1579
|
+
let t = e.config ?? {};
|
|
1580
|
+
return t.capLevelToPlayerSize === !0 || t.capLevelOnFPSDrop === !0;
|
|
1581
|
+
}
|
|
1582
|
+
var q = 8, jn = 12e4, Mn = 6e4;
|
|
1578
1583
|
function J(e, t, n) {
|
|
1579
1584
|
if (n <= 0 || t < 0 || t >= e.length) return t;
|
|
1580
1585
|
let r = (t, n) => e[t].width === e[n].width && e[t].height === e[n].height, i = (t) => {
|
|
@@ -1587,11 +1592,11 @@ function J(e, t, n) {
|
|
|
1587
1592
|
function Y() {
|
|
1588
1593
|
return typeof self < "u" && self.devicePixelRatio > 0 ? self.devicePixelRatio : 1;
|
|
1589
1594
|
}
|
|
1590
|
-
var
|
|
1591
|
-
function
|
|
1595
|
+
var Nn = .2, Pn = 30, Fn = 2, In = 2, Ln = 2, Rn = 9, zn = .5, Bn = 64, Vn = 1e4, Hn = 8, Un = .6, Wn = .4, Gn = .4, Kn = 2, qn = 6e4, X = .5, Jn = 3.5, Yn = 300;
|
|
1596
|
+
function Xn(e) {
|
|
1592
1597
|
return (e?.part ?? e?.frag)?.stats;
|
|
1593
1598
|
}
|
|
1594
|
-
function
|
|
1599
|
+
function Zn() {
|
|
1595
1600
|
if (typeof navigator > "u") return 0;
|
|
1596
1601
|
try {
|
|
1597
1602
|
let e = navigator.connection?.rtt;
|
|
@@ -1600,20 +1605,20 @@ function qn() {
|
|
|
1600
1605
|
return 0;
|
|
1601
1606
|
}
|
|
1602
1607
|
}
|
|
1603
|
-
function
|
|
1608
|
+
function Qn(e) {
|
|
1604
1609
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1605
1610
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1606
1611
|
return;
|
|
1607
1612
|
}
|
|
1608
|
-
e.liveSyncDuration ??=
|
|
1609
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1610
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1613
|
+
e.liveSyncDuration ??= Ln;
|
|
1614
|
+
let t = Math.max(12, e.liveSyncDuration + Rn);
|
|
1615
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), $n(e, e.liveSyncDuration);
|
|
1611
1616
|
}
|
|
1612
|
-
function
|
|
1617
|
+
function $n(e, t) {
|
|
1613
1618
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1614
1619
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1615
1620
|
}
|
|
1616
|
-
var
|
|
1621
|
+
var er = class {
|
|
1617
1622
|
name = "hls";
|
|
1618
1623
|
hls = null;
|
|
1619
1624
|
deps;
|
|
@@ -1702,6 +1707,11 @@ var Xn = class {
|
|
|
1702
1707
|
pushedCapLevel = -1;
|
|
1703
1708
|
pushedCapReason = null;
|
|
1704
1709
|
fpsCapBitrate = null;
|
|
1710
|
+
stallCapBitrate = null;
|
|
1711
|
+
stallCapSince = 0;
|
|
1712
|
+
stallCapTickAt = 0;
|
|
1713
|
+
stallDownCaps = 0;
|
|
1714
|
+
stallCapEnabled;
|
|
1705
1715
|
fpsCapFailedHeight = null;
|
|
1706
1716
|
fpsCapManaged = !0;
|
|
1707
1717
|
fpsLastFrames = -1;
|
|
@@ -1716,7 +1726,7 @@ var Xn = class {
|
|
|
1716
1726
|
frameCounter;
|
|
1717
1727
|
detachFrames = null;
|
|
1718
1728
|
constructor(e) {
|
|
1719
|
-
this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new ht(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1729
|
+
this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.stallCapEnabled = e.stallCap !== !1, this.frameCounter = new ht(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1720
1730
|
}
|
|
1721
1731
|
async load() {
|
|
1722
1732
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1793,7 +1803,7 @@ var Xn = class {
|
|
|
1793
1803
|
let t = e.liveSyncPosition;
|
|
1794
1804
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1795
1805
|
let { video: n } = this.deps;
|
|
1796
|
-
n.currentTime <= t +
|
|
1806
|
+
n.currentTime <= t + zn || (n.currentTime = t);
|
|
1797
1807
|
}
|
|
1798
1808
|
reanchorPartTimeline(e, t) {
|
|
1799
1809
|
let { frag: n, part: r } = t;
|
|
@@ -1869,7 +1879,7 @@ var Xn = class {
|
|
|
1869
1879
|
}), t = zt(e, f.loader);
|
|
1870
1880
|
t && (this.prefetch = e, p = h, m = g, f.fLoader = t);
|
|
1871
1881
|
}
|
|
1872
|
-
|
|
1882
|
+
Qn(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;
|
|
1873
1883
|
let _ = new e(f);
|
|
1874
1884
|
if (this.hls = _, this.armHoldBack(_, f), _.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(_, t)), _.on(e.Events.MANIFEST_PARSED, () => {
|
|
1875
1885
|
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" });
|
|
@@ -1881,10 +1891,10 @@ var Xn = class {
|
|
|
1881
1891
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1882
1892
|
}), _.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1883
1893
|
t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
|
|
1884
|
-
let n = t?.frag, r =
|
|
1894
|
+
let n = t?.frag, r = Xn(t), i = r?.loaded;
|
|
1885
1895
|
typeof i == "number" && (this.bytesLoaded += i), !this.reportedFirstBytes && typeof i == "number" && i > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1886
1896
|
let a = r?.loading;
|
|
1887
|
-
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 >
|
|
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 > Bn && this.requestTimesMs.shift()), this.sampleHoldBack(t), this.sampleHeadroom(t);
|
|
1888
1898
|
let o = n?.url;
|
|
1889
1899
|
if (o) {
|
|
1890
1900
|
let e = ft(o);
|
|
@@ -1924,7 +1934,7 @@ var Xn = class {
|
|
|
1924
1934
|
_.on(e.Events.KEY_LOADED, () => {
|
|
1925
1935
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1926
1936
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1927
|
-
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.reviewSizeCapHeadroom(), this.checkFrameDrops();
|
|
1937
|
+
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.reviewSizeCapHeadroom(), this.releaseStallCap(), this.checkFrameDrops();
|
|
1928
1938
|
}, tn), _.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1929
1939
|
this.renditionSwitches += 1;
|
|
1930
1940
|
let n = this.lastLevelIndex >= 0 ? _.levels[this.lastLevelIndex] : void 0, r = _.levels[t.level];
|
|
@@ -2044,7 +2054,7 @@ var Xn = class {
|
|
|
2044
2054
|
if (!this.sizeCapManaged || !this.defaultHeadroomApplies() || e.frag?.type !== "main" || typeof e.frag.level != "number" || typeof document < "u" && document.hidden) return;
|
|
2045
2055
|
let t = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag.duration;
|
|
2046
2056
|
if (typeof t != "number" || !(t > 0)) return;
|
|
2047
|
-
let n =
|
|
2057
|
+
let n = Xn(e)?.loading;
|
|
2048
2058
|
if (!n || !(n.start > 0) || !(n.end >= n.start)) return;
|
|
2049
2059
|
let r = this.hls?.levels?.[e.frag.level]?.bitrate;
|
|
2050
2060
|
if (!(typeof r == "number" && r > 0)) return;
|
|
@@ -2055,9 +2065,42 @@ var Xn = class {
|
|
|
2055
2065
|
bitrate: r
|
|
2056
2066
|
}), this.headroomSamples.length > 256 && this.headroomSamples.shift();
|
|
2057
2067
|
}
|
|
2058
|
-
onPlaybackStall() {
|
|
2059
|
-
let
|
|
2060
|
-
this.deps.video.seeking || !this.playingSince ||
|
|
2068
|
+
onPlaybackStall(e) {
|
|
2069
|
+
let t = Date.now();
|
|
2070
|
+
this.deps.video.seeking || !this.playingSince || t - this.playingSince < En || (this.lastStallAt = t, this.stepStallCapDown(t, e), this.headroomGranted && (this.headroomGranted = !1, this.applySizeCapUnlessPending()));
|
|
2071
|
+
}
|
|
2072
|
+
stallCapLevel(e) {
|
|
2073
|
+
if (this.stallCapBitrate == null) return -1;
|
|
2074
|
+
let t = -1;
|
|
2075
|
+
return e.levels.forEach((e, n) => {
|
|
2076
|
+
e.bitrate <= this.stallCapBitrate && (t = n);
|
|
2077
|
+
}), t < 0 ? 0 : t;
|
|
2078
|
+
}
|
|
2079
|
+
stepStallCapDown(e, t) {
|
|
2080
|
+
let n = this.hls;
|
|
2081
|
+
if (!n || !this.stallCapEnabled || An(n) || !n.autoLevelEnabled || typeof t == "number" && t >= On || this.isLiveEdgeWait(n, t ?? 0)) return;
|
|
2082
|
+
this.stallCapBitrate != null && (this.stallCapSince = e);
|
|
2083
|
+
let r = Math.max(n.levels[n.currentLevel]?.bitrate ?? 0, n.levels[n.loadLevel]?.bitrate ?? 0);
|
|
2084
|
+
if (!(r > 0)) return;
|
|
2085
|
+
let i = n.levels.map((e) => e.bitrate).filter((e) => e > 0 && e < r).sort((e, t) => t - e)[0];
|
|
2086
|
+
i != null && (this.stallCapBitrate != null && i >= this.stallCapBitrate || (this.stallCapBitrate = i, this.stallCapSince = e, this.stallDownCaps += 1, this.pushCap()));
|
|
2087
|
+
}
|
|
2088
|
+
isLiveEdgeWait(e, t) {
|
|
2089
|
+
let n = e.latestLevelDetails;
|
|
2090
|
+
if (!n?.live) return !1;
|
|
2091
|
+
let r = n.partTarget || n.targetduration;
|
|
2092
|
+
return !(r > 0) || !(n.edge > 0) ? !1 : n.edge - (this.deps.video.currentTime + t) < kn * r;
|
|
2093
|
+
}
|
|
2094
|
+
releaseStallCap() {
|
|
2095
|
+
let e = this.hls, t = Date.now(), n = this.stallCapTickAt;
|
|
2096
|
+
if (this.stallCapTickAt = t, !e || this.stallCapBitrate == null) return;
|
|
2097
|
+
if (this.deps.video.paused || this.loadSuspended || this.offlineHold) {
|
|
2098
|
+
n && (this.stallCapSince += t - Math.max(n, this.stallCapSince));
|
|
2099
|
+
return;
|
|
2100
|
+
}
|
|
2101
|
+
if (t - this.stallCapSince < Dn) return;
|
|
2102
|
+
let r = this.stallCapBitrate, i = e.levels.map((e) => e.bitrate).filter((e) => e > r).sort((e, t) => e - t)[0];
|
|
2103
|
+
this.stallCapBitrate = i ?? null, this.stallCapSince = t, this.pushCap();
|
|
2061
2104
|
}
|
|
2062
2105
|
reviewSizeCapHeadroom() {
|
|
2063
2106
|
let e = Date.now(), { video: t } = this.deps;
|
|
@@ -2068,12 +2111,12 @@ var Xn = class {
|
|
|
2068
2111
|
this.headroomGranted = !1, this.headroomSamples = [];
|
|
2069
2112
|
return;
|
|
2070
2113
|
}
|
|
2071
|
-
this.headroomSamples = this.headroomSamples.filter((t) => t.t >= e -
|
|
2114
|
+
this.headroomSamples = this.headroomSamples.filter((t) => t.t >= e - Vn);
|
|
2072
2115
|
let r = this.headroomEarned(n, e);
|
|
2073
|
-
r !== this.headroomGranted && (r || (this.headroomRegrantAt = e +
|
|
2116
|
+
r !== this.headroomGranted && (r || (this.headroomRegrantAt = e + Mn), this.headroomGranted = r, this.applySizeCapUnlessPending());
|
|
2074
2117
|
}
|
|
2075
2118
|
headroomEarned(e, t) {
|
|
2076
|
-
if (t - this.lastStallAt <
|
|
2119
|
+
if (t - this.lastStallAt < jn || !this.headroomGranted && t < this.headroomRegrantAt || !this.headroomGranted && this.headroomSamples.length < q) return !1;
|
|
2077
2120
|
let n = e.levels, r = this.sizeCapCoverLevel();
|
|
2078
2121
|
if (r == null) return this.headroomGranted;
|
|
2079
2122
|
let i = J(n, r, bn);
|
|
@@ -2101,7 +2144,8 @@ var Xn = class {
|
|
|
2101
2144
|
let t = [
|
|
2102
2145
|
["size", this.sizeCapLevel ?? -1],
|
|
2103
2146
|
["bitrate", this.bitrateCapLevel],
|
|
2104
|
-
["fps", this.fpsCapLevel(e)]
|
|
2147
|
+
["fps", this.fpsCapLevel(e)],
|
|
2148
|
+
["stall", this.stallCapLevel(e)]
|
|
2105
2149
|
], n = -1, r = null;
|
|
2106
2150
|
for (let [e, i] of t) i >= 0 && (n < 0 || i < n) && (n = i, r = e);
|
|
2107
2151
|
e.autoLevelCapping = n, this.pushedCapLevel = n, this.pushedCapReason = r;
|
|
@@ -2146,6 +2190,7 @@ var Xn = class {
|
|
|
2146
2190
|
liveRetargets: this.liveRetargets,
|
|
2147
2191
|
holdBackSteps: this.holdBackSteps,
|
|
2148
2192
|
fpsDownCaps: this.fpsDownCaps,
|
|
2193
|
+
stallDownCaps: this.stallDownCaps,
|
|
2149
2194
|
licenseTimeMs: this.licenseTimeMs,
|
|
2150
2195
|
upshifts: this.upshifts,
|
|
2151
2196
|
downshifts: this.downshifts,
|
|
@@ -2160,12 +2205,7 @@ var Xn = class {
|
|
|
2160
2205
|
let t = e.currentLevel >= 0 ? e.levels[e.currentLevel] : void 0;
|
|
2161
2206
|
t && (n.levelHeight = t.height);
|
|
2162
2207
|
let r = e.autoLevelCapping, i = r >= 0 ? e.levels[r] : void 0;
|
|
2163
|
-
|
|
2164
|
-
n.maxLevelHeight = i.height;
|
|
2165
|
-
let t = e.config ?? {};
|
|
2166
|
-
t.capLevelToPlayerSize !== !0 && t.capLevelOnFPSDrop !== !0 && r === this.pushedCapLevel && this.pushedCapReason && (n.capReason = this.pushedCapReason);
|
|
2167
|
-
}
|
|
2168
|
-
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));
|
|
2208
|
+
i && i.height > 0 && (n.maxLevelHeight = i.height, !An(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));
|
|
2169
2209
|
}
|
|
2170
2210
|
return n;
|
|
2171
2211
|
}
|
|
@@ -2250,7 +2290,7 @@ var Xn = class {
|
|
|
2250
2290
|
}), n < 0 ? 0 : n;
|
|
2251
2291
|
}
|
|
2252
2292
|
armFrameDropGrace() {
|
|
2253
|
-
this.fpsGraceTicks > 0 || (this.fpsGraceTicks =
|
|
2293
|
+
this.fpsGraceTicks > 0 || (this.fpsGraceTicks = In, this.fpsBadTicks = 0);
|
|
2254
2294
|
}
|
|
2255
2295
|
resetFrameDropWindow() {
|
|
2256
2296
|
this.fpsLastFrames = -1, this.fpsLastDropped = -1, this.fpsBadTicks = 0;
|
|
@@ -2262,7 +2302,7 @@ var Xn = class {
|
|
|
2262
2302
|
return;
|
|
2263
2303
|
}
|
|
2264
2304
|
let { totalFrames: n, dropped: r } = R(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
2265
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
2305
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Pn || o < 0) {
|
|
2266
2306
|
this.fpsBadTicks = 0;
|
|
2267
2307
|
return;
|
|
2268
2308
|
}
|
|
@@ -2270,11 +2310,11 @@ var Xn = class {
|
|
|
2270
2310
|
--this.fpsGraceTicks, this.fpsBadTicks = 0;
|
|
2271
2311
|
return;
|
|
2272
2312
|
}
|
|
2273
|
-
if (o <=
|
|
2313
|
+
if (o <= Nn * a) {
|
|
2274
2314
|
this.fpsBadTicks = 0;
|
|
2275
2315
|
return;
|
|
2276
2316
|
}
|
|
2277
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
2317
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < Fn) return;
|
|
2278
2318
|
this.fpsBadTicks = 0;
|
|
2279
2319
|
let s = e.levels, c = s[e.currentLevel];
|
|
2280
2320
|
if (!c) return;
|
|
@@ -2323,13 +2363,13 @@ var Xn = class {
|
|
|
2323
2363
|
if (!this.holdBackEnabled || this.holdBackPriorChecked || !e || (this.holdBackPriorChecked = !0, this.holdBackApplied > 0 || this.holdBackStepCount > 0)) return;
|
|
2324
2364
|
let t = e.targetLatency;
|
|
2325
2365
|
if (this.holdBackBase < 0 && typeof t == "number" && t > 0 && (this.holdBackBase = t), this.holdBackBase < 0) return;
|
|
2326
|
-
let n =
|
|
2327
|
-
if (!(n >=
|
|
2366
|
+
let n = Zn();
|
|
2367
|
+
if (!(n >= Yn)) return;
|
|
2328
2368
|
let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase + X);
|
|
2329
2369
|
i > r && (this.holdBackStepCount = 1, this.moveHoldBack(e, r, i, "connection-rtt", `connection rtt ${n} ms`));
|
|
2330
2370
|
}
|
|
2331
2371
|
holdBackCeiling(e) {
|
|
2332
|
-
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t :
|
|
2372
|
+
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : Jn, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2333
2373
|
return r > 1 ? Math.min(n, r - 1) : n;
|
|
2334
2374
|
}
|
|
2335
2375
|
sampleHoldBack(e) {
|
|
@@ -2338,7 +2378,7 @@ var Xn = class {
|
|
|
2338
2378
|
if (t !== "main" && t !== "audio") return;
|
|
2339
2379
|
let n = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag?.duration;
|
|
2340
2380
|
if (typeof n != "number" || !(n > 0)) return;
|
|
2341
|
-
let r =
|
|
2381
|
+
let r = Xn(e)?.loading;
|
|
2342
2382
|
if (!r || !(r.start > 0) || !(r.end > 0)) return;
|
|
2343
2383
|
let i = r.first > r.start ? r.first : r.end, a = Math.max(0, i - r.start) / (n * 1e3);
|
|
2344
2384
|
this.holdBackSamples.push({
|
|
@@ -2353,20 +2393,20 @@ var Xn = class {
|
|
|
2353
2393
|
this.holdBackSlowTicks = 0, this.holdBackFastSince = 0, this.holdBackSamples = [];
|
|
2354
2394
|
return;
|
|
2355
2395
|
}
|
|
2356
|
-
let t = Date.now(), n = t -
|
|
2396
|
+
let t = Date.now(), n = t - Vn, r = this.holdBackSamples, i = 0;
|
|
2357
2397
|
for (; i < r.length && r[i].t < n;) i += 1;
|
|
2358
2398
|
i > 0 && r.splice(0, i);
|
|
2359
2399
|
let a = e.targetLatency;
|
|
2360
2400
|
if (typeof a != "number" || !(a > 0)) return;
|
|
2361
2401
|
this.holdBackBase < 0 && (this.holdBackBase = a);
|
|
2362
2402
|
let o = this.holdBackBase, s = this.holdBackCeiling(e);
|
|
2363
|
-
if (r.length <
|
|
2403
|
+
if (r.length < Hn) {
|
|
2364
2404
|
this.holdBackSlowTicks = 0;
|
|
2365
2405
|
return;
|
|
2366
2406
|
}
|
|
2367
2407
|
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);
|
|
2368
|
-
if (l >=
|
|
2369
|
-
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks <
|
|
2408
|
+
if (l >= Un && u >= Wn) {
|
|
2409
|
+
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < Kn) return;
|
|
2370
2410
|
this.holdBackSlowTicks = 0;
|
|
2371
2411
|
let t = Math.ceil((s - o) / X), n = Math.ceil((a - o) / X - 1e-9);
|
|
2372
2412
|
if (n > this.holdBackStepCount && (this.holdBackStepCount = n), this.holdBackStepCount >= t) return;
|
|
@@ -2376,7 +2416,7 @@ var Xn = class {
|
|
|
2376
2416
|
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)`);
|
|
2377
2417
|
return;
|
|
2378
2418
|
}
|
|
2379
|
-
if (this.holdBackSlowTicks = 0, l >=
|
|
2419
|
+
if (this.holdBackSlowTicks = 0, l >= Gn) {
|
|
2380
2420
|
this.holdBackFastSince = 0;
|
|
2381
2421
|
return;
|
|
2382
2422
|
}
|
|
@@ -2384,7 +2424,7 @@ var Xn = class {
|
|
|
2384
2424
|
this.holdBackFastSince = t;
|
|
2385
2425
|
return;
|
|
2386
2426
|
}
|
|
2387
|
-
if (t - this.holdBackFastSince <
|
|
2427
|
+
if (t - this.holdBackFastSince < qn || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
|
|
2388
2428
|
--this.holdBackStepCount;
|
|
2389
2429
|
let f = Math.max(o, o + this.holdBackStepCount * X);
|
|
2390
2430
|
f >= a || this.moveHoldBack(e, a, f, "fast-fetches", `part fetches fast again (p95 first byte ${d} ms per 1 s of media)`);
|
|
@@ -2470,7 +2510,7 @@ var Xn = class {
|
|
|
2470
2510
|
}
|
|
2471
2511
|
}
|
|
2472
2512
|
onError(t) {
|
|
2473
|
-
if (t.details === e.ErrorDetails.BUFFER_STALLED_ERROR && this.onPlaybackStall(), t.type === e.ErrorTypes.NETWORK_ERROR && String(t.details ?? "").startsWith("frag") && (this.requestErrors += 1), !t.fatal) return;
|
|
2513
|
+
if (t.details === e.ErrorDetails.BUFFER_STALLED_ERROR && this.onPlaybackStall(t.buffer), t.type === e.ErrorTypes.NETWORK_ERROR && String(t.details ?? "").startsWith("frag") && (this.requestErrors += 1), !t.fatal) return;
|
|
2474
2514
|
let n = this.hls;
|
|
2475
2515
|
if (n) {
|
|
2476
2516
|
if (this.clearRecoveryReset(), t.type === e.ErrorTypes.KEY_SYSTEM_ERROR) {
|
|
@@ -2529,15 +2569,15 @@ var Xn = class {
|
|
|
2529
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(Mt(t.networkDetails)) : void 0;
|
|
2530
2570
|
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);
|
|
2531
2571
|
}
|
|
2532
|
-
},
|
|
2572
|
+
}, tr = 15e3, nr = 6e5, rr = 3e5, ir = 100, Z = 1, ar = 1e3, or = 3e4, sr = 1e3, cr = {
|
|
2533
2573
|
inline: "PRESENTATION_INLINE",
|
|
2534
2574
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2535
2575
|
pip: "PRESENTATION_PIP"
|
|
2536
|
-
},
|
|
2576
|
+
}, lr = {
|
|
2537
2577
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2538
2578
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2539
2579
|
none: "KEY_SYSTEM_NONE"
|
|
2540
|
-
},
|
|
2580
|
+
}, ur = /* @__PURE__ */ new Set([
|
|
2541
2581
|
"INVALID_URN",
|
|
2542
2582
|
"NOT_FOUND",
|
|
2543
2583
|
"GEO_DENIED",
|
|
@@ -2548,7 +2588,7 @@ var Xn = class {
|
|
|
2548
2588
|
"FORBIDDEN",
|
|
2549
2589
|
"RATE_LIMITED",
|
|
2550
2590
|
"TIMEOUT"
|
|
2551
|
-
]),
|
|
2591
|
+
]), dr = {
|
|
2552
2592
|
idle: "PLAYER_STATE_IDLE",
|
|
2553
2593
|
waiting: "PLAYER_STATE_WAITING",
|
|
2554
2594
|
loading: "PLAYER_STATE_LOADING",
|
|
@@ -2558,7 +2598,7 @@ var Xn = class {
|
|
|
2558
2598
|
ended: "PLAYER_STATE_ENDED",
|
|
2559
2599
|
error: "PLAYER_STATE_ERROR"
|
|
2560
2600
|
};
|
|
2561
|
-
function
|
|
2601
|
+
function fr(e) {
|
|
2562
2602
|
try {
|
|
2563
2603
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2564
2604
|
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);
|
|
@@ -2566,8 +2606,8 @@ function cr(e) {
|
|
|
2566
2606
|
return;
|
|
2567
2607
|
}
|
|
2568
2608
|
}
|
|
2569
|
-
var
|
|
2570
|
-
function
|
|
2609
|
+
var pr = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), mr = /* @__PURE__ */ new Set(), hr = /* @__PURE__ */ new Set(), gr = /* @__PURE__ */ new Set(), _r = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2610
|
+
function vr(e) {
|
|
2571
2611
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2572
2612
|
let t;
|
|
2573
2613
|
try {
|
|
@@ -2576,19 +2616,19 @@ function mr(e) {
|
|
|
2576
2616
|
} catch {
|
|
2577
2617
|
return;
|
|
2578
2618
|
}
|
|
2579
|
-
if (
|
|
2580
|
-
|
|
2581
|
-
for (let e of
|
|
2619
|
+
if (mr.has(t) && !hr.has(t)) {
|
|
2620
|
+
hr.add(t), _(_r(new URL(t).origin));
|
|
2621
|
+
for (let e of gr) e.noteCspBlocked();
|
|
2582
2622
|
}
|
|
2583
2623
|
}
|
|
2584
|
-
function
|
|
2624
|
+
function yr(e, t) {
|
|
2585
2625
|
return _(t, e), { disabledReason: t };
|
|
2586
2626
|
}
|
|
2587
|
-
function
|
|
2588
|
-
if (n) return t && !
|
|
2627
|
+
function br(e, t, n) {
|
|
2628
|
+
if (n) return t && !pr(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2589
2629
|
if (t) return { endpoint: t };
|
|
2590
|
-
if (t !== void 0) return
|
|
2591
|
-
let r =
|
|
2630
|
+
if (t !== void 0) return yr("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).");
|
|
2631
|
+
let r = fr(e);
|
|
2592
2632
|
if (r) return { endpoint: r };
|
|
2593
2633
|
let i;
|
|
2594
2634
|
try {
|
|
@@ -2596,9 +2636,9 @@ function gr(e, t, n) {
|
|
|
2596
2636
|
} catch {
|
|
2597
2637
|
i = e;
|
|
2598
2638
|
}
|
|
2599
|
-
return
|
|
2639
|
+
return yr(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).`);
|
|
2600
2640
|
}
|
|
2601
|
-
var
|
|
2641
|
+
var xr = class {
|
|
2602
2642
|
opts;
|
|
2603
2643
|
url;
|
|
2604
2644
|
cspKey;
|
|
@@ -2680,8 +2720,8 @@ var _r = class {
|
|
|
2680
2720
|
constructor(e) {
|
|
2681
2721
|
this.opts = {
|
|
2682
2722
|
...e,
|
|
2683
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2684
|
-
idleMs: e.idleMs ??
|
|
2723
|
+
heartbeatMs: e.heartbeatMs ?? tr,
|
|
2724
|
+
idleMs: e.idleMs ?? nr
|
|
2685
2725
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2686
2726
|
try {
|
|
2687
2727
|
let e = new URL(this.url);
|
|
@@ -2698,11 +2738,11 @@ var _r = class {
|
|
|
2698
2738
|
sdkVersion: this.opts.sdkVersion,
|
|
2699
2739
|
...this.opts.environment
|
|
2700
2740
|
};
|
|
2701
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2741
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), ar), 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 && mr.add(this.cspKey), document.addEventListener("securitypolicyviolation", vr), gr.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2702
2742
|
}
|
|
2703
2743
|
checkSuspension(e) {
|
|
2704
2744
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2705
|
-
let t = Math.max(this.opts.idleMs,
|
|
2745
|
+
let t = Math.max(this.opts.idleMs, rr);
|
|
2706
2746
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2707
2747
|
}
|
|
2708
2748
|
syncIdle(e) {
|
|
@@ -2723,14 +2763,14 @@ var _r = class {
|
|
|
2723
2763
|
} else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
|
|
2724
2764
|
this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
|
|
2725
2765
|
let a = {
|
|
2726
|
-
fromState:
|
|
2727
|
-
toState:
|
|
2728
|
-
presentation:
|
|
2766
|
+
fromState: dr[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2767
|
+
toState: dr[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2768
|
+
presentation: cr[this.presentation]
|
|
2729
2769
|
}, o = this.causeOf(e, t, i);
|
|
2730
2770
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2731
2771
|
}
|
|
2732
2772
|
seekInduced(e) {
|
|
2733
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2773
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < sr;
|
|
2734
2774
|
}
|
|
2735
2775
|
causeOf(e, t, n) {
|
|
2736
2776
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2804,7 +2844,7 @@ var _r = class {
|
|
|
2804
2844
|
let r = n ?? "";
|
|
2805
2845
|
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";
|
|
2806
2846
|
if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
|
|
2807
|
-
if (
|
|
2847
|
+
if (ur.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2808
2848
|
let i = t ?? "";
|
|
2809
2849
|
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";
|
|
2810
2850
|
}
|
|
@@ -2836,7 +2876,7 @@ var _r = class {
|
|
|
2836
2876
|
let l = t.droppedFrames ?? 0;
|
|
2837
2877
|
l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
|
|
2838
2878
|
let u = t.renditionSwitches ?? 0;
|
|
2839
|
-
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 =
|
|
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 = dr[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
|
|
2840
2880
|
let d = this.mutedTotalMs;
|
|
2841
2881
|
this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
|
|
2842
2882
|
let f = t.upshifts ?? 0;
|
|
@@ -2858,13 +2898,13 @@ var _r = class {
|
|
|
2858
2898
|
maybeEmitMediaInfo(e) {
|
|
2859
2899
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2860
2900
|
let t = {};
|
|
2861
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2901
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = lr[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);
|
|
2862
2902
|
let n = JSON.stringify(t);
|
|
2863
2903
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2864
2904
|
}
|
|
2865
2905
|
end(e, t) {
|
|
2866
2906
|
if (this.endedFlag) return;
|
|
2867
|
-
this.endedFlag = !0,
|
|
2907
|
+
this.endedFlag = !0, gr.delete(this);
|
|
2868
2908
|
let n = t ?? this.now();
|
|
2869
2909
|
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));
|
|
2870
2910
|
let r = this.safeSample();
|
|
@@ -2878,7 +2918,7 @@ var _r = class {
|
|
|
2878
2918
|
let c = r?.positionMs ?? 0;
|
|
2879
2919
|
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));
|
|
2880
2920
|
let l = e !== "END_REASON_ENDED";
|
|
2881
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2921
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= or && (i.abandonAfterStallMs = Math.max(Z, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= or && (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);
|
|
2882
2922
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2883
2923
|
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");
|
|
2884
2924
|
}
|
|
@@ -2898,13 +2938,13 @@ var _r = class {
|
|
|
2898
2938
|
};
|
|
2899
2939
|
}
|
|
2900
2940
|
noteCspBlocked() {
|
|
2901
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2941
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(_r(new URL(this.url).origin)));
|
|
2902
2942
|
}
|
|
2903
2943
|
cspBlocked() {
|
|
2904
|
-
return !!this.cspKey &&
|
|
2944
|
+
return !!this.cspKey && hr.has(this.cspKey);
|
|
2905
2945
|
}
|
|
2906
2946
|
enqueue(e) {
|
|
2907
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2947
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > ir;) {
|
|
2908
2948
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2909
2949
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2910
2950
|
}
|
|
@@ -2931,7 +2971,7 @@ var _r = class {
|
|
|
2931
2971
|
};
|
|
2932
2972
|
//#endregion
|
|
2933
2973
|
//#region src/core/environment.ts
|
|
2934
|
-
function
|
|
2974
|
+
function Sr() {
|
|
2935
2975
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2936
2976
|
let e;
|
|
2937
2977
|
try {
|
|
@@ -2956,14 +2996,14 @@ function vr() {
|
|
|
2956
2996
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2957
2997
|
};
|
|
2958
2998
|
}
|
|
2959
|
-
function
|
|
2999
|
+
function Cr() {
|
|
2960
3000
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2961
3001
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2962
3002
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2963
3003
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2964
3004
|
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";
|
|
2965
3005
|
}
|
|
2966
|
-
function
|
|
3006
|
+
function wr() {
|
|
2967
3007
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2968
3008
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2969
3009
|
let t = {
|
|
@@ -2982,17 +3022,17 @@ function br() {
|
|
|
2982
3022
|
}
|
|
2983
3023
|
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;
|
|
2984
3024
|
}
|
|
2985
|
-
function
|
|
2986
|
-
let t =
|
|
2987
|
-
deviceClass:
|
|
3025
|
+
function Tr(e) {
|
|
3026
|
+
let t = Sr(), n = {
|
|
3027
|
+
deviceClass: Cr(),
|
|
2988
3028
|
integration: t.integration,
|
|
2989
|
-
...
|
|
3029
|
+
...wr()
|
|
2990
3030
|
};
|
|
2991
3031
|
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);
|
|
2992
3032
|
let r = e.getBoundingClientRect?.();
|
|
2993
3033
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2994
3034
|
}
|
|
2995
|
-
async function
|
|
3035
|
+
async function Er() {
|
|
2996
3036
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2997
3037
|
if (!e?.getHighEntropyValues) return {};
|
|
2998
3038
|
try {
|
|
@@ -3004,7 +3044,7 @@ async function Sr() {
|
|
|
3004
3044
|
}
|
|
3005
3045
|
//#endregion
|
|
3006
3046
|
//#region src/core/version.ts
|
|
3007
|
-
var
|
|
3047
|
+
var Dr = "2.27.0", Or = {
|
|
3008
3048
|
accent: "#E1B600",
|
|
3009
3049
|
accentText: "#1B1C23",
|
|
3010
3050
|
background: "#0e0f13",
|
|
@@ -3015,7 +3055,7 @@ var Cr = "2.26.0", wr = {
|
|
|
3015
3055
|
border: "rgba(255, 255, 255, 0.1)",
|
|
3016
3056
|
radius: "8px",
|
|
3017
3057
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
3018
|
-
},
|
|
3058
|
+
}, kr = {
|
|
3019
3059
|
accent: "--havik-accent",
|
|
3020
3060
|
accentText: "--havik-accent-text",
|
|
3021
3061
|
background: "--havik-bg",
|
|
@@ -3027,26 +3067,26 @@ var Cr = "2.26.0", wr = {
|
|
|
3027
3067
|
radius: "--havik-radius",
|
|
3028
3068
|
fontFamily: "--havik-font"
|
|
3029
3069
|
};
|
|
3030
|
-
function
|
|
3070
|
+
function Ar(e, t) {
|
|
3031
3071
|
let n = {
|
|
3032
|
-
...
|
|
3072
|
+
...Or,
|
|
3033
3073
|
...t
|
|
3034
3074
|
};
|
|
3035
|
-
for (let t of Object.keys(
|
|
3075
|
+
for (let t of Object.keys(kr)) e.style.setProperty(kr[t], n[t]);
|
|
3036
3076
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
3037
3077
|
}
|
|
3038
3078
|
//#endregion
|
|
3039
3079
|
//#region src/ui/styles.ts
|
|
3040
|
-
var
|
|
3041
|
-
function
|
|
3042
|
-
let n = e.querySelector(`style#${
|
|
3043
|
-
if (n && (!t ||
|
|
3080
|
+
var jr = "havik-player-styles", Mr = "\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", Nr = /* @__PURE__ */ new WeakMap();
|
|
3081
|
+
function Pr(e = document, t) {
|
|
3082
|
+
let n = e.querySelector(`style#${jr}`);
|
|
3083
|
+
if (n && (!t || Nr.get(n) === t)) return;
|
|
3044
3084
|
let r = e.createElement("style");
|
|
3045
|
-
r.id =
|
|
3085
|
+
r.id = jr, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Mr, Nr.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
3046
3086
|
}
|
|
3047
3087
|
//#endregion
|
|
3048
3088
|
//#region src/ui/icons.ts
|
|
3049
|
-
var
|
|
3089
|
+
var Fr = {
|
|
3050
3090
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
3051
3091
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
3052
3092
|
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\"/>",
|
|
@@ -3060,11 +3100,11 @@ var jr = {
|
|
|
3060
3100
|
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\"/>"
|
|
3061
3101
|
};
|
|
3062
3102
|
function Q(e) {
|
|
3063
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
3103
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Fr[e]}</svg>`;
|
|
3064
3104
|
}
|
|
3065
3105
|
//#endregion
|
|
3066
3106
|
//#region src/ui/controls.ts
|
|
3067
|
-
var
|
|
3107
|
+
var Ir = 3e3, Lr = 250, Rr = /* @__PURE__ */ new Set([
|
|
3068
3108
|
"GONE",
|
|
3069
3109
|
"NOT_FOUND",
|
|
3070
3110
|
"GEO_DENIED",
|
|
@@ -3072,15 +3112,15 @@ var Mr = 3e3, Nr = 250, Pr = /* @__PURE__ */ new Set([
|
|
|
3072
3112
|
"UNAUTHORIZED",
|
|
3073
3113
|
"DRM_DEVICE_REVOKED"
|
|
3074
3114
|
]);
|
|
3075
|
-
function
|
|
3115
|
+
function zr(e) {
|
|
3076
3116
|
let t = "This match isn't available in your country";
|
|
3077
3117
|
return e ? `${t} (${e})` : t;
|
|
3078
3118
|
}
|
|
3079
|
-
var
|
|
3080
|
-
function
|
|
3081
|
-
return new
|
|
3119
|
+
var Br = "This device can't play protected video";
|
|
3120
|
+
function Vr(e) {
|
|
3121
|
+
return new Hr(e);
|
|
3082
3122
|
}
|
|
3083
|
-
var
|
|
3123
|
+
var Hr = class {
|
|
3084
3124
|
root;
|
|
3085
3125
|
video;
|
|
3086
3126
|
player;
|
|
@@ -3129,7 +3169,7 @@ var Rr = class {
|
|
|
3129
3169
|
scrubbing = !1;
|
|
3130
3170
|
offFns = [];
|
|
3131
3171
|
constructor(e) {
|
|
3132
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
3172
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Ir, 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", Pr(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");
|
|
3133
3173
|
let t = (e, t, n) => {
|
|
3134
3174
|
let r = this.doc.createElement(e);
|
|
3135
3175
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -3215,7 +3255,7 @@ var Rr = class {
|
|
|
3215
3255
|
let t = this.surfaceWasHidden;
|
|
3216
3256
|
this.tapTimer = setTimeout(() => {
|
|
3217
3257
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
3218
|
-
},
|
|
3258
|
+
}, Lr);
|
|
3219
3259
|
}
|
|
3220
3260
|
toggleBar(e) {
|
|
3221
3261
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -3230,16 +3270,19 @@ var Rr = class {
|
|
|
3230
3270
|
let t = e === "loading" || e === "buffering";
|
|
3231
3271
|
this.spinner.style.display = t && !this.statusBox ? "" : "none", (t || this.statusBox) && this.center.classList.add("havik-gone"), this.syncLive();
|
|
3232
3272
|
}
|
|
3273
|
+
isGone() {
|
|
3274
|
+
return this.player.state === "error" && this.lastError?.code === "GONE";
|
|
3275
|
+
}
|
|
3233
3276
|
syncStatus(e) {
|
|
3234
3277
|
let t = null;
|
|
3235
3278
|
if (this.statusOverlays) {
|
|
3236
|
-
let n = this.player.offline &&
|
|
3237
|
-
|
|
3279
|
+
let n = e === "ended" || this.isGone(), r = this.player.offline && !n && e !== "idle", i = !this.hasPlayed && (e === "paused" || e === "waiting");
|
|
3280
|
+
n ? t = "ended" : r && !i ? t = "offline" : e === "error" ? t = "error" : e === "waiting" ? t = "waiting" : !this.hasPlayed && (e === "idle" || e === "paused") && (t = "preplay");
|
|
3238
3281
|
}
|
|
3239
3282
|
this.renderStatus(t);
|
|
3240
3283
|
}
|
|
3241
3284
|
statusMessageFor(e) {
|
|
3242
|
-
return e === "ended" ? 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" ?
|
|
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" ? zr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? Br : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
|
|
3243
3286
|
}
|
|
3244
3287
|
renderStatus(e) {
|
|
3245
3288
|
let t = this.statusMessageFor(e);
|
|
@@ -3254,7 +3297,7 @@ var Rr = class {
|
|
|
3254
3297
|
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);
|
|
3255
3298
|
} else {
|
|
3256
3299
|
let r = this.doc.createElement("div");
|
|
3257
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
3300
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Rr.has(this.lastError.code)) {
|
|
3258
3301
|
let e = this.doc.createElement("button");
|
|
3259
3302
|
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);
|
|
3260
3303
|
}
|
|
@@ -3295,11 +3338,11 @@ var Rr = class {
|
|
|
3295
3338
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
3296
3339
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
3297
3340
|
}
|
|
3298
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
3341
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Ur(this.video.currentTime)} / ${Ur(this.video.duration)}`);
|
|
3299
3342
|
}
|
|
3300
3343
|
syncLive() {
|
|
3301
|
-
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended",
|
|
3302
|
-
this.live.style.display = t && !
|
|
3344
|
+
let e = this.player.getStats(), t = e.isLive !== !1, n = this.isGone(), r = this.player.state === "ended" || n, i = !t && !this.streamEnded() && !n;
|
|
3345
|
+
this.live.style.display = t && !r ? "" : "none", this.time.style.display = i ? "" : "none", this.seek.style.display = i ? "" : "none", this.live.classList.toggle("is-live", e.atLiveEdge !== !1 && t);
|
|
3303
3346
|
}
|
|
3304
3347
|
onSeekDown(e) {
|
|
3305
3348
|
let t = this.seekableRange();
|
|
@@ -3345,17 +3388,17 @@ var Rr = class {
|
|
|
3345
3388
|
renderQualityMenu() {
|
|
3346
3389
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
3347
3390
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
3348
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
3391
|
+
for (let n of e) this.menu.append(this.menuItem(Wr(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
3349
3392
|
}
|
|
3350
3393
|
renderAudioMenu() {
|
|
3351
3394
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
3352
3395
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
3353
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3396
|
+
for (let t of e) this.menu.append(this.menuItem(Gr(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
3354
3397
|
}
|
|
3355
3398
|
renderCcMenu() {
|
|
3356
3399
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
3357
3400
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
3358
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3401
|
+
for (let t of e) this.menu.append(this.menuItem(Kr(t), !1, () => this.player.setTextTrack(t.id)));
|
|
3359
3402
|
}
|
|
3360
3403
|
onTracksChanged() {
|
|
3361
3404
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -3460,23 +3503,23 @@ var Rr = class {
|
|
|
3460
3503
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
3461
3504
|
}
|
|
3462
3505
|
};
|
|
3463
|
-
function
|
|
3506
|
+
function Ur(e) {
|
|
3464
3507
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3465
3508
|
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");
|
|
3466
3509
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3467
3510
|
}
|
|
3468
|
-
function
|
|
3511
|
+
function Wr(e) {
|
|
3469
3512
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3470
3513
|
}
|
|
3471
|
-
function
|
|
3514
|
+
function Gr(e) {
|
|
3472
3515
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3473
3516
|
}
|
|
3474
|
-
function
|
|
3517
|
+
function Kr(e) {
|
|
3475
3518
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3476
3519
|
}
|
|
3477
3520
|
//#endregion
|
|
3478
3521
|
//#region src/managed/index.ts
|
|
3479
|
-
var
|
|
3522
|
+
var qr = 6e3, Jr = 45e3, Yr = 2e3, Xr = 3, Zr = 5e3, Qr = 2e3, $r = 48e4, ei = "keySystemLicenseRequestFailed", ti = /* @__PURE__ */ new Set([
|
|
3480
3523
|
"GONE",
|
|
3481
3524
|
"NOT_FOUND",
|
|
3482
3525
|
"INVALID_URN",
|
|
@@ -3484,27 +3527,27 @@ var Ur = 6e3, Wr = 45e3, Gr = 2e3, Kr = 3, qr = 5e3, Jr = 2e3, Yr = 48e4, Xr = "
|
|
|
3484
3527
|
"GEO_DENIED",
|
|
3485
3528
|
"DRM_DEVICE_REVOKED"
|
|
3486
3529
|
]);
|
|
3487
|
-
function
|
|
3488
|
-
return !
|
|
3530
|
+
function ni(e) {
|
|
3531
|
+
return !ti.has(e);
|
|
3489
3532
|
}
|
|
3490
|
-
function
|
|
3533
|
+
function ri(e) {
|
|
3491
3534
|
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)})`);
|
|
3492
3535
|
if (e.env !== void 0) return lt(e.env);
|
|
3493
3536
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3494
3537
|
return e.baseUrl;
|
|
3495
3538
|
}
|
|
3496
|
-
async function
|
|
3539
|
+
async function ii(e) {
|
|
3497
3540
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3498
|
-
let t =
|
|
3541
|
+
let t = ri(e);
|
|
3499
3542
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3500
3543
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3501
|
-
let r = new
|
|
3544
|
+
let r = new ai({
|
|
3502
3545
|
...e,
|
|
3503
3546
|
baseUrl: t
|
|
3504
3547
|
});
|
|
3505
3548
|
return await r.start(), r;
|
|
3506
3549
|
}
|
|
3507
|
-
var
|
|
3550
|
+
var ai = class {
|
|
3508
3551
|
opts;
|
|
3509
3552
|
abort = new AbortController();
|
|
3510
3553
|
listeners = {};
|
|
@@ -3604,7 +3647,7 @@ var ti = class {
|
|
|
3604
3647
|
setTimeout(() => {
|
|
3605
3648
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3606
3649
|
phase: i ? "unavailable" : "tooEarly",
|
|
3607
|
-
retryInMs:
|
|
3650
|
+
retryInMs: Jr,
|
|
3608
3651
|
attempt: 1,
|
|
3609
3652
|
elapsedMs: 0,
|
|
3610
3653
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3643,13 +3686,13 @@ var ti = class {
|
|
|
3643
3686
|
!a && !p() && h();
|
|
3644
3687
|
}, e);
|
|
3645
3688
|
};
|
|
3646
|
-
_(
|
|
3689
|
+
_(qr), this.armingSub = D({
|
|
3647
3690
|
eventsBaseUrl: t,
|
|
3648
3691
|
matchUrn: this.opts.matchUrn,
|
|
3649
3692
|
credential: this.opts.credential,
|
|
3650
|
-
onAlive: () => _(
|
|
3693
|
+
onAlive: () => _(Jr),
|
|
3651
3694
|
onState: (e) => {
|
|
3652
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3695
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Yr);
|
|
3653
3696
|
},
|
|
3654
3697
|
onError: () => h()
|
|
3655
3698
|
});
|
|
@@ -3694,19 +3737,19 @@ var ti = class {
|
|
|
3694
3737
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3695
3738
|
let i = e.analytics?.sid;
|
|
3696
3739
|
if (!i) return;
|
|
3697
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3740
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = br(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3698
3741
|
if (!o) {
|
|
3699
3742
|
s && setTimeout(() => {
|
|
3700
3743
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3701
3744
|
}, 0);
|
|
3702
3745
|
return;
|
|
3703
3746
|
}
|
|
3704
|
-
let c = this.opts.video, l = new
|
|
3747
|
+
let c = this.opts.video, l = new xr({
|
|
3705
3748
|
endpoint: o,
|
|
3706
3749
|
sid: i,
|
|
3707
3750
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3708
|
-
sdkVersion:
|
|
3709
|
-
environment:
|
|
3751
|
+
sdkVersion: Dr,
|
|
3752
|
+
environment: Tr(c),
|
|
3710
3753
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3711
3754
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3712
3755
|
onBlocked: (e) => setTimeout(() => {
|
|
@@ -3727,7 +3770,7 @@ var ti = class {
|
|
|
3727
3770
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3728
3771
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3729
3772
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3730
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3773
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Er().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3731
3774
|
}
|
|
3732
3775
|
currentPresentation() {
|
|
3733
3776
|
let e = this.opts.video;
|
|
@@ -3750,6 +3793,7 @@ var ti = class {
|
|
|
3750
3793
|
sizeCapHeadroom: this.opts.sizeCapHeadroom,
|
|
3751
3794
|
adaptiveHoldBack: this.opts.adaptiveHoldBack,
|
|
3752
3795
|
adaptiveHoldBackCeiling: this.opts.adaptiveHoldBackCeiling,
|
|
3796
|
+
stallCap: this.opts.stallCap,
|
|
3753
3797
|
mediaDuringKey: this.opts.mediaDuringKey,
|
|
3754
3798
|
preloadHints: this.opts.preloadHints,
|
|
3755
3799
|
debug: this.opts.debug,
|
|
@@ -3759,9 +3803,9 @@ var ti = class {
|
|
|
3759
3803
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3760
3804
|
}, o = this.opts.engine ?? "auto";
|
|
3761
3805
|
if (o === "native") return new H(a);
|
|
3762
|
-
if (o === "hls") return new
|
|
3806
|
+
if (o === "hls") return new er(a);
|
|
3763
3807
|
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V() || !e.drmEnabled && Ot() && B(this.opts.video)) return new H(a);
|
|
3764
|
-
if (Wt()) return new
|
|
3808
|
+
if (Wt()) return new er(a);
|
|
3765
3809
|
if (B(this.opts.video)) return new H(a);
|
|
3766
3810
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3767
3811
|
}
|
|
@@ -3832,7 +3876,7 @@ var ti = class {
|
|
|
3832
3876
|
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."));
|
|
3833
3877
|
return;
|
|
3834
3878
|
}
|
|
3835
|
-
i += 1, i >=
|
|
3879
|
+
i += 1, i >= Xr && (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.`)));
|
|
3836
3880
|
}
|
|
3837
3881
|
}
|
|
3838
3882
|
});
|
|
@@ -3849,7 +3893,7 @@ var ti = class {
|
|
|
3849
3893
|
}
|
|
3850
3894
|
if (this.emit("online"), this._state !== "error" || !this._lastError) return;
|
|
3851
3895
|
let t = this._lastError.code;
|
|
3852
|
-
|
|
3896
|
+
ni(t) && (t === "NETWORK" || this.failedWhileOffline) && this.retry().catch(() => void 0);
|
|
3853
3897
|
}));
|
|
3854
3898
|
}
|
|
3855
3899
|
watchReturn() {
|
|
@@ -3859,7 +3903,7 @@ var ti = class {
|
|
|
3859
3903
|
return;
|
|
3860
3904
|
}
|
|
3861
3905
|
let e = this.hiddenAtMs;
|
|
3862
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3906
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= Zr && this.resyncLiveState();
|
|
3863
3907
|
}, this.onReturnPageShow = (e) => {
|
|
3864
3908
|
e.persisted && this.resyncLiveState();
|
|
3865
3909
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3891,7 +3935,7 @@ var ti = class {
|
|
|
3891
3935
|
scheduleRejoin(e) {
|
|
3892
3936
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3893
3937
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3894
|
-
}, Math.random() *
|
|
3938
|
+
}, Math.random() * Yr));
|
|
3895
3939
|
}
|
|
3896
3940
|
cancelRejoin() {
|
|
3897
3941
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3915,7 +3959,7 @@ var ti = class {
|
|
|
3915
3959
|
}
|
|
3916
3960
|
t.controls = !1;
|
|
3917
3961
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3918
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3962
|
+
r && r.insertBefore(n, t), n.appendChild(t), Ar(n, this.opts.theme), this.container = n, this.controlBar = Vr({
|
|
3919
3963
|
root: n,
|
|
3920
3964
|
video: t,
|
|
3921
3965
|
player: this,
|
|
@@ -3954,7 +3998,7 @@ var ti = class {
|
|
|
3954
3998
|
}
|
|
3955
3999
|
startStats() {
|
|
3956
4000
|
this.stopStats();
|
|
3957
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
4001
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Qr);
|
|
3958
4002
|
this.statsTimer = setInterval(() => {
|
|
3959
4003
|
if (!this.engine) return;
|
|
3960
4004
|
let e = this.engine.getStats();
|
|
@@ -3965,14 +4009,14 @@ var ti = class {
|
|
|
3965
4009
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3966
4010
|
}
|
|
3967
4011
|
isStaleLicenseDenial(e) {
|
|
3968
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
4012
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== ei || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : W(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3969
4013
|
}
|
|
3970
4014
|
scheduleLicenseRefresh() {
|
|
3971
4015
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3972
4016
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3973
4017
|
document.visibilityState !== "visible" || this.destroyed || W(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3974
4018
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3975
|
-
let e = this.opts.licenseRefreshMs ??
|
|
4019
|
+
let e = this.opts.licenseRefreshMs ?? $r;
|
|
3976
4020
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3977
4021
|
}
|
|
3978
4022
|
stopRefresh() {
|
|
@@ -4142,7 +4186,7 @@ function $(e) {
|
|
|
4142
4186
|
}
|
|
4143
4187
|
//#endregion
|
|
4144
4188
|
//#region src/embed/host.ts
|
|
4145
|
-
function
|
|
4189
|
+
function oi(e) {
|
|
4146
4190
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
4147
4191
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
4148
4192
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -4201,15 +4245,15 @@ function ni(e) {
|
|
|
4201
4245
|
}
|
|
4202
4246
|
//#endregion
|
|
4203
4247
|
//#region src/embed/page.ts
|
|
4204
|
-
var
|
|
4205
|
-
function
|
|
4248
|
+
var si = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
4249
|
+
function ci(e) {
|
|
4206
4250
|
if (typeof e == "boolean") return e;
|
|
4207
4251
|
if (typeof e == "object" && e) {
|
|
4208
4252
|
let t = e.endpoint;
|
|
4209
4253
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
4210
4254
|
}
|
|
4211
4255
|
}
|
|
4212
|
-
function
|
|
4256
|
+
function li() {
|
|
4213
4257
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
4214
4258
|
if (e) return {
|
|
4215
4259
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -4219,7 +4263,7 @@ function ai() {
|
|
|
4219
4263
|
autoplay: e.autoplay ?? !0,
|
|
4220
4264
|
muted: e.muted ?? !0,
|
|
4221
4265
|
waitForLive: e.waitForLive ?? !0,
|
|
4222
|
-
analytics:
|
|
4266
|
+
analytics: ci(e.analytics)
|
|
4223
4267
|
};
|
|
4224
4268
|
let t = new URLSearchParams(location.search);
|
|
4225
4269
|
return {
|
|
@@ -4232,9 +4276,9 @@ function ai() {
|
|
|
4232
4276
|
waitForLive: !0
|
|
4233
4277
|
};
|
|
4234
4278
|
}
|
|
4235
|
-
async function
|
|
4236
|
-
let e =
|
|
4237
|
-
|
|
4279
|
+
async function ui() {
|
|
4280
|
+
let e = li();
|
|
4281
|
+
fi();
|
|
4238
4282
|
let t = document.createElement("video");
|
|
4239
4283
|
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);
|
|
4240
4284
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -4290,12 +4334,12 @@ async function oi() {
|
|
|
4290
4334
|
message: e.message,
|
|
4291
4335
|
...e.country === void 0 ? {} : { country: e.country }
|
|
4292
4336
|
})), e.on("autoplayblocked", () => {
|
|
4293
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
4337
|
+
i({ type: "oddin:autoplayblocked" }), di(t, e);
|
|
4294
4338
|
});
|
|
4295
4339
|
}, s = async (r) => {
|
|
4296
4340
|
a?.destroy(), a = null;
|
|
4297
4341
|
try {
|
|
4298
|
-
let n = await
|
|
4342
|
+
let n = await ii({
|
|
4299
4343
|
video: t,
|
|
4300
4344
|
baseUrl: e.baseUrl,
|
|
4301
4345
|
matchUrn: r,
|
|
@@ -4358,7 +4402,7 @@ async function oi() {
|
|
|
4358
4402
|
a?.retry();
|
|
4359
4403
|
break;
|
|
4360
4404
|
case "oddin:load":
|
|
4361
|
-
typeof e.matchUrn == "string" &&
|
|
4405
|
+
typeof e.matchUrn == "string" && si.test(e.matchUrn) && s(e.matchUrn);
|
|
4362
4406
|
break;
|
|
4363
4407
|
case "oddin:destroy": c();
|
|
4364
4408
|
}
|
|
@@ -4370,18 +4414,18 @@ async function oi() {
|
|
|
4370
4414
|
protocol: 1
|
|
4371
4415
|
});
|
|
4372
4416
|
}
|
|
4373
|
-
function
|
|
4417
|
+
function di(e, t) {
|
|
4374
4418
|
if (document.getElementById("havik-tap")) return;
|
|
4375
4419
|
let n = document.createElement("button");
|
|
4376
4420
|
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", () => {
|
|
4377
4421
|
n.remove(), t.play();
|
|
4378
4422
|
}), document.body.appendChild(n);
|
|
4379
4423
|
}
|
|
4380
|
-
function
|
|
4424
|
+
function fi() {
|
|
4381
4425
|
let e = document.createElement("style");
|
|
4382
4426
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
4383
4427
|
}
|
|
4384
4428
|
//#endregion
|
|
4385
|
-
export { E as LiveStateHttpError,
|
|
4429
|
+
export { E as LiveStateHttpError, Or as ODDIN_THEME, n as PlaybackError, Ar as applyTheme, lt as baseUrlForEnv, ui as bootEmbed, ke as clearDeviceId, He as clearRememberedBandwidth, ii 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, oi as mountEmbed, fe as pollToLive, y as resolveStream, D as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
|
|
4386
4430
|
|
|
4387
4431
|
//# sourceMappingURL=index.js.map
|