mirror of
https://github.com/redphx/better-xcloud.git
synced 2025-06-28 18:31:44 +02:00
Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
1929834c98 | |||
6e80ea08e8 | |||
a5caafa93a | |||
f8134c3e5a | |||
89ea55774b | |||
2836eeb6ed | |||
876b090ad2 | |||
e33730b124 | |||
8b4f26155c | |||
a52ba7dddf | |||
a8eb296bcf | |||
f4a3c38cca | |||
e8ab19c318 | |||
89e4dd0003 | |||
9874d36f3a | |||
ed54d1ed38 | |||
4676e42215 | |||
ad791bdc45 |
56
README.md
56
README.md
@ -2,21 +2,29 @@
|
||||
Improve [Xbox Cloud Gaming (xCloud)](https://www.xbox.com/play/) experience on web browser.
|
||||
The main target of this script is mobile users, but it should work great on desktop too.
|
||||
|
||||
Give this project a 🌟 if you like it. Thank you.
|
||||
Give this project a 🌟 if you like it. Thank you 🙏.
|
||||
|
||||
## Features
|
||||
|
||||
<img width="500" alt="Settings UI" src="https://github.com/redphx/better-xcloud/assets/96280/4f60c2e6-9706-4326-940f-f46998177633">
|
||||
<img width="500" alt="Video Settings UI" src="https://github.com/redphx/better-xcloud/assets/96280/130aa870-6938-4604-9e23-45e217b800cc">
|
||||
<img width="500" alt="Settings UI" src="https://github.com/redphx/better-xcloud/assets/96280/8fb9f0ac-85f5-4e5a-9570-5a5e119e4fc1">
|
||||
<img width="500" alt="Video Settings UI" src="https://github.com/redphx/better-xcloud/assets/96280/ed219d50-02ab-40bd-95c5-a010956d77bf">
|
||||
|
||||
|
||||
- **Switch region of streaming server**
|
||||
> Connect to another server instead of the default one. Check [FAQ section](#faq) for some notes.
|
||||
> Connect to another server instead of the default one. Check [FAQ section](#faq) for some notes.
|
||||
> Not working in Hermit ([#5](https://github.com/redphx/better-xcloud/issues/5)).
|
||||
- **Force 1080p stream**
|
||||
> By default you only get 1080p stream when playing on desktop.
|
||||
> This feature will give you 1080p stream even on mobile, without having to change User-Agent.
|
||||
> Not working in Hermit ([#5](https://github.com/redphx/better-xcloud/issues/5)).
|
||||
- **Force high quality codec <sup>(\*)</sup>**
|
||||
> Force xCloud to use the best streaming codec profile (same as desktop & TV). You don't have to change User-Agent anymore.
|
||||
> You should enable this feature even if you're on desktop.
|
||||
> Use more bandwidth & battery.
|
||||
> Comparison video with the setting ON & OFF: https://youtu.be/-9PuBJJSgR4
|
||||
> Disable if it causes crashes.
|
||||
- **Prefer IPv6 streaming server**
|
||||
> Might reduce latency
|
||||
- **Force high quality stream**
|
||||
> Force xCloud to use the best streaming codec profile (same as desktop). You don't have to change User-Agent anymore.
|
||||
> Some browsers (like Firefox) don't support this feature. Check [the full list](https://caniuse.com/?search=setCodecPreferences).
|
||||
> If you're on Android and want to use it, try [Hermit](https://hermit.chimbori.com).
|
||||
- **Disable bandwidth checking**
|
||||
> xCloud won't reduce quality when the internet speed is slow
|
||||
- **Skip Xbox splash video**
|
||||
@ -29,12 +37,18 @@ Give this project a 🌟 if you like it. Thank you.
|
||||
> Useful when you don't have a 16:9 screen
|
||||
- **Adjust video filters**
|
||||
> Brightness/Contrast/Saturation
|
||||
- **Display stream's statuses**
|
||||
> Region/Server/Quality/Dimension...
|
||||
- **Disable social features**
|
||||
> Features like friends, chat... Disable these will make the page load faster.
|
||||
> Features like friends, chat... Disable these will make the page load faster.
|
||||
> Not working in Hermit ([#5](https://github.com/redphx/better-xcloud/issues/5)).
|
||||
- **Disable xCloud analytics**
|
||||
> The analytics contains statistics of your streaming session, so I'd recommend to allow analytics to help Xbox improve xCloud's experence in the future.
|
||||
> The analytics contains statistics of your streaming session, so I'd recommend to allow analytics to help Xbox improve xCloud's experence in the future.
|
||||
> Not working in Hermit ([#5](https://github.com/redphx/better-xcloud/issues/5)).
|
||||
- **Hide footer and other UI elements**
|
||||
|
||||
<sup>(\*)</sup> By default (for compatibility reasons) xCloud only uses high quality codec profile when you use Tizen TV or Chrome/Edge/Chromium browser on Chrome/MacOS. Enable this setting will give you the best experience no matter what platform & browser you're on.
|
||||
|
||||
## How to use
|
||||
1. Install [Tampermonkey extension](https://www.tampermonkey.net/) on suppported browsers. It's also available for Firefox on Android.
|
||||
2. Install **Better xCloud**:
|
||||
@ -60,8 +74,8 @@ To update manually, just install the script again (you won't lose your settings)
|
||||
|
||||
Don't see your browser in the table? If it supports Tampermonkey/Userscript then the answer is likely **"YES"**.
|
||||
|
||||
<sup>1, 2</sup> Requires [Userscripts app](https://apps.apple.com/us/app/userscripts/id1463298887).
|
||||
<sup>3</sup> NOT RECOMMENDED at the moment since its Userscript implementation is not working properly. Non-network related features (skip splash video, video settings...) still work. It's still my favorite app to play xCloud on because it's lightweight, supports Userscript (premium features, only $1.99) without having to install anything else. I built **Better xCloud** just so I could use it with Hermit.
|
||||
<sup>1, 2</sup> Requires [Userscripts app](https://apps.apple.com/us/app/userscripts/id1463298887) (free & open source).
|
||||
<sup>3</sup> NOT RECOMMENDED at the moment since its Userscript implementation is not working properly (see https://github.com/redphx/better-xcloud/issues/5 for full details). It's still my favorite app to play xCloud on because it's lightweight, supports Userscript (premium features, only $1.99) without having to install anything else. I built **Better xCloud** just so I could use it with Hermit.
|
||||
|
||||
## FAQ
|
||||
1. **Will I get banned for using this?**
|
||||
@ -79,14 +93,15 @@ No you can't. You'll have to modify the app.
|
||||
5. **Will you able to enable "Clarity Boost" feature on non-Edge browsers?**
|
||||
No. "Clarity Boost" feature uses an exclusive API (`Video.msVideoProcessing`) that's only available on Edge browser for desktop at the moment.
|
||||
|
||||
## Acknowledgements
|
||||
- [n-thumann/xbox-cloud-server-selector](https://github.com/n-thumann/xbox-cloud-server-selector) for the idea of IPv6 feature
|
||||
- Icons by [Adam Design](https://www.iconfinder.com/iconsets/user-interface-outline-27)
|
||||
|
||||
## User-Agent
|
||||
> You're no longer needed to change User-Agent since you can just use the **Force high quality stream** setting.
|
||||
> I'll still keep this section because it has some interesting info.
|
||||
You're no longer needed to change User-Agent since you can just use the **Force high quality stream** setting.
|
||||
If your browser doesn't support **Force high quality stream** setting, try changing User-Agent to:
|
||||
```
|
||||
Mozilla/5.0 (SMART-TV; LINUX; Tizen 7.0) AppleWebKit/537.36 (KHTML, like Gecko) 94.0.4606.31/7.0 TV Safari/537.36
|
||||
```
|
||||
This will change your device to a Samsung TV running Tizen OS. It will improve the stream quality.
|
||||
|
||||
---
|
||||
Change User-Agent to:
|
||||
```
|
||||
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.67
|
||||
@ -99,7 +114,10 @@ Other options (only do one of these):
|
||||
- Add ` 36102dd3-6953-45f6-8b48-031fb95e0e0d` to become a Logitech G Cloud device.
|
||||
- Add ` 0ed22b6f-b61d-41eb-810a-a1ed586a550b` to become a Razer Edge device.
|
||||
|
||||
## Acknowledgements
|
||||
- [n-thumann/xbox-cloud-server-selector](https://github.com/n-thumann/xbox-cloud-server-selector) for the idea of IPv6 feature
|
||||
- Icons by [Adam Design](https://www.iconfinder.com/iconsets/user-interface-outline-27)
|
||||
|
||||
## Disclaimers
|
||||
- Use as your own risk.
|
||||
- This project is not affiliated with Xbox in any way. All Xbox logos/icons/trademarks are copyright of their respective owners.
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @name Better xCloud
|
||||
// @namespace https://github.com/redphx
|
||||
// @version 1.3.1
|
||||
// @version 1.4
|
||||
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
||||
// @author redphx
|
||||
// @license MIT
|
||||
@ -13,15 +13,47 @@
|
||||
// ==/UserScript==
|
||||
'use strict';
|
||||
|
||||
const SCRIPT_VERSION = '1.3.1';
|
||||
const SCRIPT_VERSION = '1.4';
|
||||
const SCRIPT_HOME = 'https://github.com/redphx/better-xcloud';
|
||||
|
||||
const SERVER_REGIONS = {};
|
||||
|
||||
|
||||
class StreamStatus {
|
||||
static ipv6 = false;
|
||||
static dimension = {width: 0, height: 0};
|
||||
static hqCodec = false;
|
||||
static region = '';
|
||||
|
||||
static #renderBadge(name, value, color) {
|
||||
const CE = createElement;
|
||||
const $badge = CE('div', {'class': 'better_xcloud_badge'},
|
||||
CE('span', {'class': 'better_xcloud_badge_name'}, name),
|
||||
CE('span', {'class': 'better_xcloud_badge_value', 'style': `background-color: ${color}`}, value));
|
||||
|
||||
return $badge;
|
||||
}
|
||||
|
||||
static render() {
|
||||
const BADGES = [
|
||||
['region', StreamStatus.region, '#d7450b'],
|
||||
['server', StreamStatus.ipv6 ? 'IPv6' : 'IPv4', '#008746'],
|
||||
['quality', StreamStatus.hqCodec ? 'High' : 'Normal', '#007c8f'],
|
||||
['dimension', `${StreamStatus.dimension.width}x${StreamStatus.dimension.height}`, '#ff3977'],
|
||||
];
|
||||
|
||||
const $wrapper = createElement('div', {'class': 'better_xcloud_badges'});
|
||||
BADGES.forEach(item => $wrapper.appendChild(StreamStatus.#renderBadge(...item)));
|
||||
|
||||
return $wrapper;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Preferences {
|
||||
static get SERVER_REGION() { return 'server_region'; }
|
||||
static get PREFER_IPV6_SERVER() { return 'prefer_ipv6_server'; }
|
||||
static get FORCE_1080P_STREAM() { return 'force_1080p_stream'; }
|
||||
static get USE_DESKTOP_CODEC() { return 'use_desktop_codec'; }
|
||||
|
||||
static get BLOCK_TRACKING() { return 'block_tracking'; }
|
||||
@ -43,21 +75,27 @@ class Preferences {
|
||||
'default': 'default',
|
||||
},
|
||||
|
||||
{
|
||||
'id': Preferences.FORCE_1080P_STREAM,
|
||||
'label': 'Force 1080p stream',
|
||||
'default': false,
|
||||
},
|
||||
|
||||
{
|
||||
'id': Preferences.USE_DESKTOP_CODEC,
|
||||
'label': 'Force high quality codec',
|
||||
'default': false,
|
||||
},
|
||||
|
||||
{
|
||||
'id': Preferences.PREFER_IPV6_SERVER,
|
||||
'label': 'Prefer IPv6 streaming server',
|
||||
'default': false,
|
||||
},
|
||||
|
||||
{
|
||||
'id': Preferences.USE_DESKTOP_CODEC,
|
||||
'label': 'Force high quality stream (same as desktop)',
|
||||
'default': false,
|
||||
},
|
||||
|
||||
{
|
||||
'id': Preferences.DISABLE_BANDWIDTH_CHECKING,
|
||||
'label': 'Disable bandwitdh checking',
|
||||
'label': 'Disable bandwidth checking',
|
||||
'default': false,
|
||||
},
|
||||
|
||||
@ -81,7 +119,7 @@ class Preferences {
|
||||
|
||||
{
|
||||
'id': Preferences.BLOCK_SOCIAL_FEATURES,
|
||||
'label': 'Disable social features (Friends, Chat...)',
|
||||
'label': 'Disable social features',
|
||||
'default': false,
|
||||
},
|
||||
|
||||
@ -193,7 +231,7 @@ function addCss() {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.better_xcloud_settings_button:hover, .better_xlcoud_settings_button:focus {
|
||||
.better_xcloud_settings_button:hover, .better_xcloud_settings_button:focus {
|
||||
background-color: #515863;
|
||||
}
|
||||
|
||||
@ -209,9 +247,9 @@ function addCss() {
|
||||
}
|
||||
|
||||
.better_xcloud_settings_wrapper {
|
||||
width: 400px;
|
||||
width: 450px;
|
||||
margin: auto;
|
||||
padding: 12px;
|
||||
padding: 12px 6px;
|
||||
}
|
||||
|
||||
.better_xcloud_settings_wrapper *:focus {
|
||||
@ -225,11 +263,23 @@ function addCss() {
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
color: #5dc21e;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
.better_xcloud_settings_wrapper a:hover {
|
||||
color: #83f73a;
|
||||
}
|
||||
}
|
||||
|
||||
.better_xcloud_settings_wrapper a:focus {
|
||||
color: #83f73a;
|
||||
}
|
||||
|
||||
.better_xcloud_settings_wrapper .setting_row {
|
||||
display: flex;
|
||||
margin-bottom: 8px;
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
.better_xcloud_settings_wrapper .setting_row label {
|
||||
@ -238,6 +288,12 @@ function addCss() {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@media not (hover: hover) {
|
||||
.better_xcloud_settings_wrapper .setting_row:focus-within {
|
||||
background-color: #242424;
|
||||
}
|
||||
}
|
||||
|
||||
.better_xcloud_settings_wrapper .setting_row input {
|
||||
align-self: center;
|
||||
}
|
||||
@ -263,8 +319,48 @@ function addCss() {
|
||||
}
|
||||
}
|
||||
|
||||
.better_xcloud_settings_wrapper .setting_button:focus {
|
||||
background-color: #00753c;
|
||||
}
|
||||
|
||||
.better_xcloud_settings_wrapper .setting_button:active {
|
||||
background-color: #00753c;
|
||||
background-color: #00753c;
|
||||
}
|
||||
|
||||
div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module] {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.better_xcloud_badges {
|
||||
position: absolute;
|
||||
bottom: -35px;
|
||||
margin-left: 0px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.better_xcloud_badge {
|
||||
border: none;
|
||||
display: inline-block;
|
||||
line-height: 24px;
|
||||
color: #fff;
|
||||
font-family: Bahnschrift Semibold, Arial, Helvetica, sans-serif;
|
||||
font-weight: 400;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.better_xcloud_badge .better_xcloud_badge_name {
|
||||
background-color: #2d3036;
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px 0 0 4px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.better_xcloud_badge .better_xcloud_badge_value {
|
||||
background-color: grey;
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
/* Hide UI elements */
|
||||
@ -340,7 +436,7 @@ function getPreferredServerRegion() {
|
||||
|
||||
|
||||
function updateIceCandidates(candidates) {
|
||||
const pattern = new RegExp(/a=candidate:(?<order>\d+) (?<num>\d+) UDP (?<priority>\d+) (?<ip>[^\s]+) (?<the_rest>.*)/);
|
||||
const pattern = new RegExp(/a=candidate:(?<foundation>\d+) (?<component>\d+) UDP (?<priority>\d+) (?<ip>[^\s]+) (?<the_rest>.*)/);
|
||||
|
||||
const lst = [];
|
||||
for (let item of candidates) {
|
||||
@ -355,21 +451,19 @@ function updateIceCandidates(candidates) {
|
||||
lst.sort((a, b) => (a.ip.includes(':') || a.ip > b.ip) ? -1 : 1);
|
||||
|
||||
const newCandidates = [];
|
||||
let order = 1;
|
||||
let priority = 100;
|
||||
let foundation = 1;
|
||||
lst.forEach(item => {
|
||||
item.order = order;
|
||||
item.priority = priority;
|
||||
item.foundation = foundation;
|
||||
item.priority = (foundation == 1) ? 100 : 1;
|
||||
|
||||
newCandidates.push({
|
||||
'candidate': `a=candidate:${item.order} 1 UDP ${item.priority} ${item.ip} ${item.the_rest}`,
|
||||
'candidate': `a=candidate:${item.foundation} 1 UDP ${item.priority} ${item.ip} ${item.the_rest}`,
|
||||
'messageType': 'iceCandidate',
|
||||
'sdpMLineIndex': '0',
|
||||
'sdpMid': '0',
|
||||
});
|
||||
|
||||
++order;
|
||||
--priority;
|
||||
++foundation;
|
||||
});
|
||||
|
||||
newCandidates.push({
|
||||
@ -428,6 +522,9 @@ function interceptHttpRequests() {
|
||||
};
|
||||
|
||||
const PREF_PREFER_IPV6_SERVER = PREFS.get(Preferences.PREFER_IPV6_SERVER);
|
||||
const PREF_FORCE_1080P_STREAM = PREFS.get(Preferences.FORCE_1080P_STREAM);
|
||||
const PREF_USE_DESKTOP_CODEC = PREFS.get(Preferences.USE_DESKTOP_CODEC);
|
||||
const HAS_CODECS_API_SUPPORT = hasRtcSetCodecPreferencesSupport();
|
||||
|
||||
const orgFetch = window.fetch;
|
||||
window.fetch = async (...arg) => {
|
||||
@ -468,8 +565,59 @@ function interceptHttpRequests() {
|
||||
});
|
||||
}
|
||||
|
||||
// Get region
|
||||
if (url.endsWith('/sessions/cloud/play')) {
|
||||
const parsedUrl = new URL(url);
|
||||
|
||||
StreamStatus.region = parsedUrl.host.split('.', 1)[0];
|
||||
for (let regionName in SERVER_REGIONS) {
|
||||
const region = SERVER_REGIONS[regionName];
|
||||
if (parsedUrl.origin == region.baseUri) {
|
||||
StreamStatus.region = regionName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Force 1080p stream
|
||||
if (PREF_FORCE_1080P_STREAM) {
|
||||
// Intercept "osName" value
|
||||
const clone = request.clone();
|
||||
const body = await clone.json();
|
||||
body.settings.osName = 'windows';
|
||||
|
||||
const newRequest = new Request(request, {
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
|
||||
arg[0] = newRequest;
|
||||
}
|
||||
|
||||
return orgFetch(...arg);
|
||||
}
|
||||
|
||||
// Work-around for browsers with no setCodecPreferences() support
|
||||
if (PREF_USE_DESKTOP_CODEC && !HAS_CODECS_API_SUPPORT && url.endsWith('/sdp') && url.includes('/sessions/cloud/') && request.method === 'GET') {
|
||||
const promise = orgFetch(...arg);
|
||||
|
||||
return promise.then(response => {
|
||||
return response.clone().text().then(text => {
|
||||
if (!text.length) {
|
||||
return response;
|
||||
}
|
||||
|
||||
const obj = JSON.parse(text);
|
||||
obj.exchangeResponse = obj.exchangeResponse.replaceAll('profile-level-id=42', 'profile-level-id=4d');
|
||||
|
||||
response.json = () => Promise.resolve(obj);
|
||||
response.text = () => Promise.resolve(JSON.stringify(obj));
|
||||
|
||||
return response;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ICE server candidates
|
||||
if (PREF_PREFER_IPV6_SERVER && url.endsWith('/ice') && url.includes('/sessions/cloud/')) {
|
||||
if (PREF_PREFER_IPV6_SERVER && url.endsWith('/ice') && url.includes('/sessions/cloud/') && request.method === 'GET') {
|
||||
const promise = orgFetch(...arg);
|
||||
|
||||
return promise.then(response => {
|
||||
@ -484,6 +632,8 @@ function interceptHttpRequests() {
|
||||
obj.exchangeResponse = JSON.stringify(exchangeResponse);
|
||||
|
||||
response.json = () => Promise.resolve(obj);
|
||||
response.text = () => Promise.resolve(JSON.stringify(obj));
|
||||
|
||||
return response;
|
||||
});
|
||||
});
|
||||
@ -569,6 +719,7 @@ function injectSettingsButton($parent) {
|
||||
}
|
||||
|
||||
let $control;
|
||||
let labelAttrs = {};
|
||||
if (setting.id === Preferences.SERVER_REGION) {
|
||||
$control = CE('select', {id: 'xcloud_setting_' + setting.id});
|
||||
$control.addEventListener('change', e => {
|
||||
@ -608,22 +759,18 @@ function injectSettingsButton($parent) {
|
||||
setting.value = PREFS.get(setting.id);
|
||||
$control.checked = setting.value;
|
||||
|
||||
if (setting.id === Preferences.USE_DESKTOP_CODEC && !hasRtcSetCodecPreferencesSupport()) {
|
||||
$control.disabled = true;
|
||||
$control.checked = false;
|
||||
$control.title = 'Not supported by this browser';
|
||||
}
|
||||
labelAttrs = {'for': 'xcloud_setting_' + setting.id, 'tabindex': 0};
|
||||
}
|
||||
|
||||
const $elm = CE('div', {'class': 'setting_row'},
|
||||
CE('label', {'for': 'xcloud_setting_' + setting.id}, setting.label),
|
||||
CE('label', labelAttrs, setting.label),
|
||||
$control
|
||||
);
|
||||
|
||||
$wrapper.appendChild($elm);
|
||||
}
|
||||
|
||||
const $reloadBtn = CE('button', {'class': 'setting_button'}, 'Reload page to reflect changes');
|
||||
const $reloadBtn = CE('button', {'class': 'setting_button', 'tabindex': 0}, 'Reload page to reflect changes');
|
||||
$reloadBtn.addEventListener('click', e => window.location.reload());
|
||||
$wrapper.appendChild($reloadBtn);
|
||||
|
||||
@ -796,9 +943,6 @@ function injectVideoSettingsButton() {
|
||||
// Show Quick settings bar
|
||||
$quickBar.style.display = 'flex';
|
||||
|
||||
// Close HUD
|
||||
document.querySelector('button[class*=StreamMenu-module__backButton]').click();
|
||||
|
||||
$parent.addEventListener('click', hideQuickBarFunc);
|
||||
$parent.addEventListener('touchend', hideQuickBarFunc);
|
||||
|
||||
@ -809,6 +953,15 @@ function injectVideoSettingsButton() {
|
||||
});
|
||||
|
||||
$orgButton.parentElement.insertBefore($button, $orgButton.parentElement.firstChild);
|
||||
|
||||
// Hide Quick bar when closing HUD
|
||||
document.querySelector('button[class*=StreamMenu-module__backButton]').addEventListener('click', e => {
|
||||
$quickBar.style.display = 'none';
|
||||
});
|
||||
|
||||
// Render stream badges
|
||||
const $menu = document.querySelector('div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module]');
|
||||
$menu.appendChild(StreamStatus.render());
|
||||
});
|
||||
|
||||
});
|
||||
@ -825,6 +978,10 @@ function patchVideoApi() {
|
||||
showFunc = function() {
|
||||
this.style.visibility = 'visible';
|
||||
this.removeEventListener('playing', showFunc);
|
||||
|
||||
if (this.videoWidth) {
|
||||
StreamStatus.dimension = {width: this.videoWidth, height: this.videoHeight};
|
||||
}
|
||||
}
|
||||
|
||||
HTMLMediaElement.prototype.orgPlay = HTMLMediaElement.prototype.play;
|
||||
@ -1114,3 +1271,24 @@ window.onload = () => {
|
||||
if (document.readyState === 'complete' && !onLoadTriggered) {
|
||||
watchHeader();
|
||||
}
|
||||
|
||||
|
||||
RTCPeerConnection.prototype.orgSetRemoteDescription = RTCPeerConnection.prototype.setRemoteDescription;
|
||||
RTCPeerConnection.prototype.setRemoteDescription = function(...args) {
|
||||
const sdpDesc = args[0];
|
||||
if (sdpDesc.sdp) {
|
||||
StreamStatus.hqCodec = sdpDesc.sdp.includes('profile-level-id=4d');
|
||||
}
|
||||
return this.orgSetRemoteDescription.apply(this, args);
|
||||
}
|
||||
|
||||
|
||||
RTCPeerConnection.prototype.orgAddIceCandidate = RTCPeerConnection.prototype.addIceCandidate;
|
||||
RTCPeerConnection.prototype.addIceCandidate = function(...args) {
|
||||
const candidate = args[0].candidate;
|
||||
if (candidate && candidate.startsWith('a=candidate:1 ')) {
|
||||
StreamStatus.ipv6 = candidate.substring(20).includes(':');
|
||||
}
|
||||
|
||||
return this.orgAddIceCandidate.apply(this, args);
|
||||
}
|
||||
|
Reference in New Issue
Block a user