Forces Twitch streams to always start at the highest quality available.
// ==UserScript==
// @name Twitch Force Max Quality
// @name:de Twitch Maximale Qualität Erzwingen
// @name:fr Twitch Forcer la Qualité Maximale
// @name:es Twitch Forzar máxima calidad
// @name:it Twitch Forza la massima qualità
// @name:zh-CN Twitch 强制最高画质
// @description Forces Twitch streams to always start at the highest quality available.
// @description:de Erzwingt, dass Twitch-Streams immer in der höchstmöglichen Qualität starten.
// @description:fr Force les flux Twitch à toujours démarrer mit der höchsten verfügbaren Qualität.
// @description:es Fuerza a que los streams de Twitch comiencen siempre con la máxima calidad disponible.
// @description:it Forza gli streaming di Twitch ad avviarsi sempre con la massima qualità disponible.
// @description:zh-CN 强制 Twitch 流始终以最高可用画质开始。
// @version 0.0.5
// @author Wack.3gp (https://greasyfork.org/users/4792)
// @copyright 2026+, Wack.3gp
// @namespace https://greasyfork.org/users/4792
// @license CC BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/
// @icon https://assets.twitch.tv/assets/favicon-32-e29e246c157142c94346.png
// @match https://www.twitch.tv/*
// @exclude https://www.twitch.tv/settings*
// @exclude https://www.twitch.tv/wallet*
// @exclude https://www.twitch.tv/inventory*
// @exclude https://www.twitch.tv/dashboard*
// @grant none
// @run-at document-end
// @supportURL https://greasyfork.org/scripts/577775/feedback
// @contributionURL https://www.paypal.com/donate/?hosted_button_id=BYW9D395KJWZ2
// @contributionAmount €1.00
// ==/UserScript==
/* jshint esversion: 11 */
(function() {
'use strict';
const DONATE_URL = "https://www.paypal.com/donate/?hosted_button_id=BYW9D395KJWZ2";
function showSupportPopup() {
if (document.getElementById('bmc-support-popup')) return;
const popup = document.createElement('div');
popup.id = 'bmc-support-popup';
popup.innerHTML = `
<div style="font-weight: bold; margin-bottom: 6px; color: #adadb8; font-size: 14px;">☕ Buy me a coffee</div>
<div style="margin-bottom: 12px; line-height: 1.4;">If you like my work, feel free to support the development of this script!</div>
<div style="display: flex; gap: 8px;">
<button id="bmc-btn-donate" style="background-color: #9146ff; color: white; border: none; padding: 6px 12px; border-radius: 4px; font-weight: bold; cursor: pointer; font-size: 12px; transition: background-color 0.2s;">Donate via PayPal</button>
<button id="bmc-btn-close" style="background-color: #3a3a3c; color: #efeff1; border: none; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 12px; transition: background-color 0.2s;">Close</button>
</div>
`;
const style = document.createElement('style');
style.id = 'bmc-popup-style';
style.innerHTML = `
#bmc-support-popup {
position: fixed;
bottom: 75px;
left: 20px;
background-color: #18181b;
color: #efeff1;
border: 1px solid #3a3a3c;
border-left: 4px solid #9146ff;
padding: 14px;
border-radius: 6px;
box-shadow: 0 4px 16px rgba(0,0,0,0.6);
z-index: 10000;
font-family: Inter, Roobert, Helvetica Neue, Helvetica, Arial, sans-serif;
font-size: 13px;
width: 260px;
animation: bmcPopIn 0.2s ease forwards;
}
#bmc-btn-donate:hover { background-color: #772ce8; }
#bmc-btn-close:hover { background-color: #4e4e50; }
@keyframes bmcPopIn {
from { opacity: 0; transform: translateY(10px) scale(0.95); }
to { opacity: 1; transform: translateY(0) scale(1); }
}
`;
document.head.appendChild(style);
document.body.appendChild(popup);
document.getElementById('bmc-btn-donate').addEventListener('click', () => {
window.open(DONATE_URL, '_blank');
closePopup(popup, style);
});
document.getElementById('bmc-btn-close').addEventListener('click', () => {
closePopup(popup, style);
});
}
function closePopup(popup, style) {
popup.style.transition = "opacity 0.2s ease, transform 0.2s ease";
popup.style.opacity = "0";
popup.style.transform = "translateY(10px) scale(0.95)";
setTimeout(() => {
popup.remove();
style.remove();
}, 200);
}
function addCoffeeButton() {
if (document.getElementById('bmc-twitch-trigger')) return;
const button = document.createElement('div');
button.id = 'bmc-twitch-trigger';
button.title = 'Support Wack.3gp (Buy me a coffee)';
button.innerHTML = `
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor">
<path d="M2 21h18v-2H2v2M20 8h-2V5h2v3M4 19h12V5H4v14m14-14h2v1H18V5m0 5h2V8h-2v2m0 3h2v-1h-2v1m0 2h1v-1h-1v1M4 3h16a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"/>
</svg>
`;
const style = document.createElement('style');
style.innerHTML = `
#bmc-twitch-trigger {
position: fixed;
bottom: 20px;
left: 20px;
width: 40px;
height: 40px;
background-color: #9146ff;
color: #ffffff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
z-index: 9999;
transition: transform 0.2s ease, background-color 0.2s ease;
cursor: pointer;
}
#bmc-twitch-trigger:hover {
transform: scale(1.1);
background-color: #772ce8;
}
`;
button.addEventListener('click', (e) => {
e.preventDefault();
showSupportPopup();
});
document.head.appendChild(style);
document.body.appendChild(button);
}
async function setHighestQualitySilent(playerContainer) {
const settingsBtn = playerContainer.querySelector('[data-a-target="player-settings-button"]');
if (!settingsBtn) return;
const style = document.createElement('style');
style.id = 'silent-quality-fix';
style.innerHTML = `
[data-a-target="player-settings-menu"],
.video-player__settings-menu {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
pointer-events: none !important;
}
`;
document.head.appendChild(style);
try {
settingsBtn.click();
await new Promise(r => setTimeout(r, 200));
const qualityMenu = Array.from(document.querySelectorAll('button'))
.find(el => {
const text = el.textContent.toLowerCase();
return text.includes('qualit') || text.includes('画质') || text.includes('calidad');
});
if (qualityMenu) {
qualityMenu.click();
await new Promise(r => setTimeout(r, 200));
const options = Array.from(document.querySelectorAll('[role="menuitemradio"]'));
const bestOption = options
.map(el => {
const text = el.textContent.trim();
const compStyle = window.getComputedStyle(el);
const isAuto = text.toLowerCase().includes('auto') || text.includes('自动');
const isDisabled = el.getAttribute('aria-disabled') === 'true' || parseFloat(compStyle.opacity) < 0.6;
const res = parseInt(text.match(/(\d+)p/)?.[1] || "0");
return { el, text, isAuto, isDisabled, res };
})
.filter(o => !o.isAuto && !o.isDisabled && o.res > 0)
.sort((a, b) => b.res - a.res)[0];
if (bestOption) {
const isChecked = bestOption.el.querySelector('[data-a-target="tw-core-svg"]');
if (!isChecked) {
bestOption.el.click();
console.log("[Twitch-Fix] Successfully switched to " + bestOption.text);
}
}
}
} catch (e) {
console.error("[Twitch-Fix] Error switching quality:", e);
} finally {
await new Promise(r => setTimeout(r, 150));
style.remove();
if (document.querySelector('[data-a-target="player-settings-menu"]')) {
settingsBtn.click();
}
}
}
addCoffeeButton();
let lastUrl = "";
setInterval(() => {
const currentUrl = window.location.href;
addCoffeeButton();
const players = document.querySelectorAll('.video-player, .featured-content-carousel__video-player');
players.forEach(player => {
if (currentUrl !== lastUrl || !player.dataset.qualityChecked) {
lastUrl = currentUrl;
player.dataset.qualityChecked = "true";
setTimeout(() => setHighestQualitySilent(player), 3000);
}
});
}, 4000);
})();