mirror of
https://github.com/redphx/better-xcloud.git
synced 2025-06-26 09:23:04 +02:00
Update dist
This commit is contained in:
54
dist/better-xcloud.lite.user.js
vendored
54
dist/better-xcloud.lite.user.js
vendored
@ -959,7 +959,8 @@ class StreamStatsCollector {
|
|||||||
fps: {
|
fps: {
|
||||||
current: 0,
|
current: 0,
|
||||||
toString() {
|
toString() {
|
||||||
return this.current.toString();
|
const maxFps = getPref("video_max_fps");
|
||||||
|
return maxFps < 60 ? `${maxFps}/${this.current}` : this.current.toString();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
btr: {
|
btr: {
|
||||||
@ -4689,7 +4690,23 @@ class StreamBadges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
class XcloudInterceptor {
|
class XcloudInterceptor {
|
||||||
static async#handleLogin(request, init) {
|
static SERVER_EMOJIS = {
|
||||||
|
AustraliaEast: "🇦🇺",
|
||||||
|
AustraliaSouthEast: "🇦🇺",
|
||||||
|
BrazilSouth: "🇧🇷",
|
||||||
|
EastUS: "🇺🇸",
|
||||||
|
EastUS2: "🇺🇸",
|
||||||
|
JapanEast: "🇯🇵",
|
||||||
|
KoreaCentral: "🇰🇷",
|
||||||
|
MexicoCentral: "🇲🇽",
|
||||||
|
NorthCentralUs: "🇺🇸",
|
||||||
|
SouthCentralUS: "🇺🇸",
|
||||||
|
UKSouth: "🇬🇧",
|
||||||
|
WestEurope: "🇪🇺",
|
||||||
|
WestUS: "🇺🇸",
|
||||||
|
WestUS2: "🇺🇸"
|
||||||
|
};
|
||||||
|
static async handleLogin(request, init) {
|
||||||
const bypassServer = getPref("server_bypass_restriction");
|
const bypassServer = getPref("server_bypass_restriction");
|
||||||
if (bypassServer !== "off") {
|
if (bypassServer !== "off") {
|
||||||
const ip = BypassServerIps[bypassServer];
|
const ip = BypassServerIps[bypassServer];
|
||||||
@ -4699,22 +4716,7 @@ class XcloudInterceptor {
|
|||||||
if (response.status !== 200) return BxEvent.dispatch(window, BxEvent.XCLOUD_SERVERS_UNAVAILABLE), response;
|
if (response.status !== 200) return BxEvent.dispatch(window, BxEvent.XCLOUD_SERVERS_UNAVAILABLE), response;
|
||||||
const obj = await response.clone().json();
|
const obj = await response.clone().json();
|
||||||
RemotePlayManager.getInstance().xcloudToken = obj.gsToken;
|
RemotePlayManager.getInstance().xcloudToken = obj.gsToken;
|
||||||
const serverEmojis = {
|
const serverRegex = /\/\/(\w+)\./, serverEmojis = XcloudInterceptor.SERVER_EMOJIS;
|
||||||
AustraliaEast: "🇦🇺",
|
|
||||||
AustraliaSouthEast: "🇦🇺",
|
|
||||||
BrazilSouth: "🇧🇷",
|
|
||||||
EastUS: "🇺🇸",
|
|
||||||
EastUS2: "🇺🇸",
|
|
||||||
JapanEast: "🇯🇵",
|
|
||||||
KoreaCentral: "🇰🇷",
|
|
||||||
MexicoCentral: "🇲🇽",
|
|
||||||
NorthCentralUs: "🇺🇸",
|
|
||||||
SouthCentralUS: "🇺🇸",
|
|
||||||
UKSouth: "🇬🇧",
|
|
||||||
WestEurope: "🇪🇺",
|
|
||||||
WestUS: "🇺🇸",
|
|
||||||
WestUS2: "🇺🇸"
|
|
||||||
}, serverRegex = /\/\/(\w+)\./;
|
|
||||||
for (let region of obj.offeringSettings.regions) {
|
for (let region of obj.offeringSettings.regions) {
|
||||||
const regionName = region.name;
|
const regionName = region.name;
|
||||||
let shortName = region.name;
|
let shortName = region.name;
|
||||||
@ -4733,7 +4735,7 @@ class XcloudInterceptor {
|
|||||||
}
|
}
|
||||||
return STATES.gsToken = obj.gsToken, response.json = () => Promise.resolve(obj), response;
|
return STATES.gsToken = obj.gsToken, response.json = () => Promise.resolve(obj), response;
|
||||||
}
|
}
|
||||||
static async#handlePlay(request, init) {
|
static async handlePlay(request, init) {
|
||||||
const PREF_STREAM_TARGET_RESOLUTION = getPref("stream_target_resolution"), PREF_STREAM_PREFERRED_LOCALE = getPref("stream_preferred_locale"), url = typeof request === "string" ? request : request.url, parsedUrl = new URL(url);
|
const PREF_STREAM_TARGET_RESOLUTION = getPref("stream_target_resolution"), PREF_STREAM_PREFERRED_LOCALE = getPref("stream_preferred_locale"), url = typeof request === "string" ? request : request.url, parsedUrl = new URL(url);
|
||||||
let badgeRegion = parsedUrl.host.split(".", 1)[0];
|
let badgeRegion = parsedUrl.host.split(".", 1)[0];
|
||||||
for (let regionName in STATES.serverRegions) {
|
for (let regionName in STATES.serverRegions) {
|
||||||
@ -4755,7 +4757,7 @@ class XcloudInterceptor {
|
|||||||
});
|
});
|
||||||
return NATIVE_FETCH(newRequest);
|
return NATIVE_FETCH(newRequest);
|
||||||
}
|
}
|
||||||
static async#handleWaitTime(request, init) {
|
static async handleWaitTime(request, init) {
|
||||||
const response = await NATIVE_FETCH(request, init);
|
const response = await NATIVE_FETCH(request, init);
|
||||||
if (getPref("ui_loading_screen_wait_time")) {
|
if (getPref("ui_loading_screen_wait_time")) {
|
||||||
const json = await response.clone().json();
|
const json = await response.clone().json();
|
||||||
@ -4763,7 +4765,7 @@ class XcloudInterceptor {
|
|||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
static async#handleConfiguration(request, init) {
|
static async handleConfiguration(request, init) {
|
||||||
if (request.method !== "GET") return NATIVE_FETCH(request, init);
|
if (request.method !== "GET") return NATIVE_FETCH(request, init);
|
||||||
const response = await NATIVE_FETCH(request, init), text = await response.clone().text();
|
const response = await NATIVE_FETCH(request, init), text = await response.clone().text();
|
||||||
if (!text.length) return response;
|
if (!text.length) return response;
|
||||||
@ -4782,10 +4784,10 @@ class XcloudInterceptor {
|
|||||||
}
|
}
|
||||||
static async handle(request, init) {
|
static async handle(request, init) {
|
||||||
let url = typeof request === "string" ? request : request.url;
|
let url = typeof request === "string" ? request : request.url;
|
||||||
if (url.endsWith("/v2/login/user")) return XcloudInterceptor.#handleLogin(request, init);
|
if (url.endsWith("/v2/login/user")) return XcloudInterceptor.handleLogin(request, init);
|
||||||
else if (url.endsWith("/sessions/cloud/play")) return XcloudInterceptor.#handlePlay(request, init);
|
else if (url.endsWith("/sessions/cloud/play")) return XcloudInterceptor.handlePlay(request, init);
|
||||||
else if (url.includes("xboxlive.com") && url.includes("/waittime/")) return XcloudInterceptor.#handleWaitTime(request, init);
|
else if (url.includes("xboxlive.com") && url.includes("/waittime/")) return XcloudInterceptor.handleWaitTime(request, init);
|
||||||
else if (url.endsWith("/configuration")) return XcloudInterceptor.#handleConfiguration(request, init);
|
else if (url.endsWith("/configuration")) return XcloudInterceptor.handleConfiguration(request, init);
|
||||||
else if (url && url.endsWith("/ice") && url.includes("/sessions/") && request.method === "GET") return patchIceCandidates(request);
|
else if (url && url.endsWith("/ice") && url.includes("/sessions/") && request.method === "GET") return patchIceCandidates(request);
|
||||||
return NATIVE_FETCH(request, init);
|
return NATIVE_FETCH(request, init);
|
||||||
}
|
}
|
||||||
@ -5054,7 +5056,7 @@ class WebGL2Player {
|
|||||||
saturation: 0
|
saturation: 0
|
||||||
};
|
};
|
||||||
targetFps = 60;
|
targetFps = 60;
|
||||||
frameInterval = Math.ceil(1000 / this.targetFps);
|
frameInterval = 0;
|
||||||
lastFrameTime = 0;
|
lastFrameTime = 0;
|
||||||
animFrameId = null;
|
animFrameId = null;
|
||||||
constructor($video) {
|
constructor($video) {
|
||||||
|
84
dist/better-xcloud.user.js
vendored
84
dist/better-xcloud.user.js
vendored
@ -986,7 +986,8 @@ class StreamStatsCollector {
|
|||||||
fps: {
|
fps: {
|
||||||
current: 0,
|
current: 0,
|
||||||
toString() {
|
toString() {
|
||||||
return this.current.toString();
|
const maxFps = getPref("video_max_fps");
|
||||||
|
return maxFps < 60 ? `${maxFps}/${this.current}` : this.current.toString();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
btr: {
|
btr: {
|
||||||
@ -5988,7 +5989,7 @@ class RemotePlayManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
class XhomeInterceptor {
|
class XhomeInterceptor {
|
||||||
static #consoleAddrs = {};
|
static consoleAddrs = {};
|
||||||
static BASE_DEVICE_INFO = {
|
static BASE_DEVICE_INFO = {
|
||||||
appInfo: {
|
appInfo: {
|
||||||
env: {
|
env: {
|
||||||
@ -6027,7 +6028,7 @@ class XhomeInterceptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static async#handleLogin(request) {
|
static async handleLogin(request) {
|
||||||
try {
|
try {
|
||||||
const obj = await request.clone().json();
|
const obj = await request.clone().json();
|
||||||
obj.offeringId = "xhome", request = new Request("https://xhome.gssv-play-prod.xboxlive.com/v2/login/user", {
|
obj.offeringId = "xhome", request = new Request("https://xhome.gssv-play-prod.xboxlive.com/v2/login/user", {
|
||||||
@ -6042,19 +6043,19 @@ class XhomeInterceptor {
|
|||||||
}
|
}
|
||||||
return NATIVE_FETCH(request);
|
return NATIVE_FETCH(request);
|
||||||
}
|
}
|
||||||
static async#handleConfiguration(request) {
|
static async handleConfiguration(request) {
|
||||||
const response = await NATIVE_FETCH(request), obj = await response.clone().json();
|
const response = await NATIVE_FETCH(request), obj = await response.clone().json();
|
||||||
console.log(obj);
|
console.log(obj);
|
||||||
const processPorts = (port) => {
|
const processPorts = (port) => {
|
||||||
const ports = new Set;
|
const ports = new Set;
|
||||||
return port && ports.add(port), ports.add(9002), Array.from(ports);
|
return port && ports.add(port), ports.add(9002), Array.from(ports);
|
||||||
}, serverDetails = obj.serverDetails;
|
}, serverDetails = obj.serverDetails;
|
||||||
if (serverDetails.ipAddress) XhomeInterceptor.#consoleAddrs[serverDetails.ipAddress] = processPorts(serverDetails.port);
|
if (serverDetails.ipAddress) XhomeInterceptor.consoleAddrs[serverDetails.ipAddress] = processPorts(serverDetails.port);
|
||||||
if (serverDetails.ipV4Address) XhomeInterceptor.#consoleAddrs[serverDetails.ipV4Address] = processPorts(serverDetails.ipV4Port);
|
if (serverDetails.ipV4Address) XhomeInterceptor.consoleAddrs[serverDetails.ipV4Address] = processPorts(serverDetails.ipV4Port);
|
||||||
if (serverDetails.ipV6Address) XhomeInterceptor.#consoleAddrs[serverDetails.ipV6Address] = processPorts(serverDetails.ipV6Port);
|
if (serverDetails.ipV6Address) XhomeInterceptor.consoleAddrs[serverDetails.ipV6Address] = processPorts(serverDetails.ipV6Port);
|
||||||
return response.json = () => Promise.resolve(obj), response.text = () => Promise.resolve(JSON.stringify(obj)), response;
|
return response.json = () => Promise.resolve(obj), response.text = () => Promise.resolve(JSON.stringify(obj)), response;
|
||||||
}
|
}
|
||||||
static async#handleInputConfigs(request, opts) {
|
static async handleInputConfigs(request, opts) {
|
||||||
const response = await NATIVE_FETCH(request);
|
const response = await NATIVE_FETCH(request);
|
||||||
if (getPref("stream_touch_controller") !== "all") return response;
|
if (getPref("stream_touch_controller") !== "all") return response;
|
||||||
const obj = await response.clone().json(), xboxTitleId = JSON.parse(opts.body).titleIds[0];
|
const obj = await response.clone().json(), xboxTitleId = JSON.parse(opts.body).titleIds[0];
|
||||||
@ -6071,7 +6072,7 @@ class XhomeInterceptor {
|
|||||||
else TouchController.enable(), TouchController.requestCustomLayouts(xboxTitleId);
|
else TouchController.enable(), TouchController.requestCustomLayouts(xboxTitleId);
|
||||||
return response.json = () => Promise.resolve(obj), response.text = () => Promise.resolve(JSON.stringify(obj)), response;
|
return response.json = () => Promise.resolve(obj), response.text = () => Promise.resolve(JSON.stringify(obj)), response;
|
||||||
}
|
}
|
||||||
static async#handleTitles(request) {
|
static async handleTitles(request) {
|
||||||
const clone = request.clone(), headers = {};
|
const clone = request.clone(), headers = {};
|
||||||
for (let pair of clone.headers.entries())
|
for (let pair of clone.headers.entries())
|
||||||
headers[pair[0]] = pair[1];
|
headers[pair[0]] = pair[1];
|
||||||
@ -6083,7 +6084,7 @@ class XhomeInterceptor {
|
|||||||
headers
|
headers
|
||||||
}), NATIVE_FETCH(request);
|
}), NATIVE_FETCH(request);
|
||||||
}
|
}
|
||||||
static async#handlePlay(request) {
|
static async handlePlay(request) {
|
||||||
const body = await request.clone().json(), newRequest = new Request(request, {
|
const body = await request.clone().json(), newRequest = new Request(request, {
|
||||||
body: JSON.stringify(body)
|
body: JSON.stringify(body)
|
||||||
});
|
});
|
||||||
@ -6110,12 +6111,12 @@ class XhomeInterceptor {
|
|||||||
}
|
}
|
||||||
request = new Request(newUrl, opts);
|
request = new Request(newUrl, opts);
|
||||||
let url = typeof request === "string" ? request : request.url;
|
let url = typeof request === "string" ? request : request.url;
|
||||||
if (url.includes("/configuration")) return XhomeInterceptor.#handleConfiguration(request);
|
if (url.includes("/configuration")) return XhomeInterceptor.handleConfiguration(request);
|
||||||
else if (url.endsWith("/sessions/home/play")) return XhomeInterceptor.#handlePlay(request);
|
else if (url.endsWith("/sessions/home/play")) return XhomeInterceptor.handlePlay(request);
|
||||||
else if (url.includes("inputconfigs")) return XhomeInterceptor.#handleInputConfigs(request, opts);
|
else if (url.includes("inputconfigs")) return XhomeInterceptor.handleInputConfigs(request, opts);
|
||||||
else if (url.includes("/login/user")) return XhomeInterceptor.#handleLogin(request);
|
else if (url.includes("/login/user")) return XhomeInterceptor.handleLogin(request);
|
||||||
else if (url.endsWith("/titles")) return XhomeInterceptor.#handleTitles(request);
|
else if (url.endsWith("/titles")) return XhomeInterceptor.handleTitles(request);
|
||||||
else if (url && url.endsWith("/ice") && url.includes("/sessions/") && request.method === "GET") return patchIceCandidates(request, XhomeInterceptor.#consoleAddrs);
|
else if (url && url.endsWith("/ice") && url.includes("/sessions/") && request.method === "GET") return patchIceCandidates(request, XhomeInterceptor.consoleAddrs);
|
||||||
return await NATIVE_FETCH(request);
|
return await NATIVE_FETCH(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6549,7 +6550,23 @@ class StreamBadges {
|
|||||||
static setupEvents() {}
|
static setupEvents() {}
|
||||||
}
|
}
|
||||||
class XcloudInterceptor {
|
class XcloudInterceptor {
|
||||||
static async#handleLogin(request, init) {
|
static SERVER_EMOJIS = {
|
||||||
|
AustraliaEast: "🇦🇺",
|
||||||
|
AustraliaSouthEast: "🇦🇺",
|
||||||
|
BrazilSouth: "🇧🇷",
|
||||||
|
EastUS: "🇺🇸",
|
||||||
|
EastUS2: "🇺🇸",
|
||||||
|
JapanEast: "🇯🇵",
|
||||||
|
KoreaCentral: "🇰🇷",
|
||||||
|
MexicoCentral: "🇲🇽",
|
||||||
|
NorthCentralUs: "🇺🇸",
|
||||||
|
SouthCentralUS: "🇺🇸",
|
||||||
|
UKSouth: "🇬🇧",
|
||||||
|
WestEurope: "🇪🇺",
|
||||||
|
WestUS: "🇺🇸",
|
||||||
|
WestUS2: "🇺🇸"
|
||||||
|
};
|
||||||
|
static async handleLogin(request, init) {
|
||||||
const bypassServer = getPref("server_bypass_restriction");
|
const bypassServer = getPref("server_bypass_restriction");
|
||||||
if (bypassServer !== "off") {
|
if (bypassServer !== "off") {
|
||||||
const ip = BypassServerIps[bypassServer];
|
const ip = BypassServerIps[bypassServer];
|
||||||
@ -6559,22 +6576,7 @@ class XcloudInterceptor {
|
|||||||
if (response.status !== 200) return BxEvent.dispatch(window, BxEvent.XCLOUD_SERVERS_UNAVAILABLE), response;
|
if (response.status !== 200) return BxEvent.dispatch(window, BxEvent.XCLOUD_SERVERS_UNAVAILABLE), response;
|
||||||
const obj = await response.clone().json();
|
const obj = await response.clone().json();
|
||||||
RemotePlayManager.getInstance().xcloudToken = obj.gsToken;
|
RemotePlayManager.getInstance().xcloudToken = obj.gsToken;
|
||||||
const serverEmojis = {
|
const serverRegex = /\/\/(\w+)\./, serverEmojis = XcloudInterceptor.SERVER_EMOJIS;
|
||||||
AustraliaEast: "🇦🇺",
|
|
||||||
AustraliaSouthEast: "🇦🇺",
|
|
||||||
BrazilSouth: "🇧🇷",
|
|
||||||
EastUS: "🇺🇸",
|
|
||||||
EastUS2: "🇺🇸",
|
|
||||||
JapanEast: "🇯🇵",
|
|
||||||
KoreaCentral: "🇰🇷",
|
|
||||||
MexicoCentral: "🇲🇽",
|
|
||||||
NorthCentralUs: "🇺🇸",
|
|
||||||
SouthCentralUS: "🇺🇸",
|
|
||||||
UKSouth: "🇬🇧",
|
|
||||||
WestEurope: "🇪🇺",
|
|
||||||
WestUS: "🇺🇸",
|
|
||||||
WestUS2: "🇺🇸"
|
|
||||||
}, serverRegex = /\/\/(\w+)\./;
|
|
||||||
for (let region of obj.offeringSettings.regions) {
|
for (let region of obj.offeringSettings.regions) {
|
||||||
const regionName = region.name;
|
const regionName = region.name;
|
||||||
let shortName = region.name;
|
let shortName = region.name;
|
||||||
@ -6593,7 +6595,7 @@ class XcloudInterceptor {
|
|||||||
}
|
}
|
||||||
return STATES.gsToken = obj.gsToken, response.json = () => Promise.resolve(obj), response;
|
return STATES.gsToken = obj.gsToken, response.json = () => Promise.resolve(obj), response;
|
||||||
}
|
}
|
||||||
static async#handlePlay(request, init) {
|
static async handlePlay(request, init) {
|
||||||
const PREF_STREAM_TARGET_RESOLUTION = getPref("stream_target_resolution"), PREF_STREAM_PREFERRED_LOCALE = getPref("stream_preferred_locale"), url = typeof request === "string" ? request : request.url, parsedUrl = new URL(url);
|
const PREF_STREAM_TARGET_RESOLUTION = getPref("stream_target_resolution"), PREF_STREAM_PREFERRED_LOCALE = getPref("stream_preferred_locale"), url = typeof request === "string" ? request : request.url, parsedUrl = new URL(url);
|
||||||
let badgeRegion = parsedUrl.host.split(".", 1)[0];
|
let badgeRegion = parsedUrl.host.split(".", 1)[0];
|
||||||
for (let regionName in STATES.serverRegions) {
|
for (let regionName in STATES.serverRegions) {
|
||||||
@ -6615,7 +6617,7 @@ class XcloudInterceptor {
|
|||||||
});
|
});
|
||||||
return NATIVE_FETCH(newRequest);
|
return NATIVE_FETCH(newRequest);
|
||||||
}
|
}
|
||||||
static async#handleWaitTime(request, init) {
|
static async handleWaitTime(request, init) {
|
||||||
const response = await NATIVE_FETCH(request, init);
|
const response = await NATIVE_FETCH(request, init);
|
||||||
if (getPref("ui_loading_screen_wait_time")) {
|
if (getPref("ui_loading_screen_wait_time")) {
|
||||||
const json = await response.clone().json();
|
const json = await response.clone().json();
|
||||||
@ -6623,7 +6625,7 @@ class XcloudInterceptor {
|
|||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
static async#handleConfiguration(request, init) {
|
static async handleConfiguration(request, init) {
|
||||||
if (request.method !== "GET") return NATIVE_FETCH(request, init);
|
if (request.method !== "GET") return NATIVE_FETCH(request, init);
|
||||||
if (getPref("stream_touch_controller") === "all") if (STATES.currentStream.titleInfo?.details.hasTouchSupport) TouchController.disable();
|
if (getPref("stream_touch_controller") === "all") if (STATES.currentStream.titleInfo?.details.hasTouchSupport) TouchController.disable();
|
||||||
else TouchController.enable();
|
else TouchController.enable();
|
||||||
@ -6645,10 +6647,10 @@ class XcloudInterceptor {
|
|||||||
}
|
}
|
||||||
static async handle(request, init) {
|
static async handle(request, init) {
|
||||||
let url = typeof request === "string" ? request : request.url;
|
let url = typeof request === "string" ? request : request.url;
|
||||||
if (url.endsWith("/v2/login/user")) return XcloudInterceptor.#handleLogin(request, init);
|
if (url.endsWith("/v2/login/user")) return XcloudInterceptor.handleLogin(request, init);
|
||||||
else if (url.endsWith("/sessions/cloud/play")) return XcloudInterceptor.#handlePlay(request, init);
|
else if (url.endsWith("/sessions/cloud/play")) return XcloudInterceptor.handlePlay(request, init);
|
||||||
else if (url.includes("xboxlive.com") && url.includes("/waittime/")) return XcloudInterceptor.#handleWaitTime(request, init);
|
else if (url.includes("xboxlive.com") && url.includes("/waittime/")) return XcloudInterceptor.handleWaitTime(request, init);
|
||||||
else if (url.endsWith("/configuration")) return XcloudInterceptor.#handleConfiguration(request, init);
|
else if (url.endsWith("/configuration")) return XcloudInterceptor.handleConfiguration(request, init);
|
||||||
else if (url && url.endsWith("/ice") && url.includes("/sessions/") && request.method === "GET") return patchIceCandidates(request);
|
else if (url && url.endsWith("/ice") && url.includes("/sessions/") && request.method === "GET") return patchIceCandidates(request);
|
||||||
return NATIVE_FETCH(request, init);
|
return NATIVE_FETCH(request, init);
|
||||||
}
|
}
|
||||||
@ -6959,7 +6961,7 @@ class WebGL2Player {
|
|||||||
saturation: 0
|
saturation: 0
|
||||||
};
|
};
|
||||||
targetFps = 60;
|
targetFps = 60;
|
||||||
frameInterval = Math.ceil(1000 / this.targetFps);
|
frameInterval = 0;
|
||||||
lastFrameTime = 0;
|
lastFrameTime = 0;
|
||||||
animFrameId = null;
|
animFrameId = null;
|
||||||
constructor($video) {
|
constructor($video) {
|
||||||
|
Reference in New Issue
Block a user