// ==UserScript== // @name Twitch - Auto Best Video Quality // @namespace http://tampermonkey.net/ // @version 2.1 // @description Twitch - Auto Best Video Quality (1440p, 1080p, 720p etc) // @author Martin______X // @match https://www.twitch.tv/* // @icon https://www.google.com/s2/favicons?sz=64&domain=twitch.tv // @grant none // @license MIT // @downloadURL none // ==/UserScript== let $url = ""; let $click_times = 0; let $step = 1; let $delay = 0; let $video_height = 0; const simpleClick = ((target, step) => { if (target) { target.click(); } if (step == 5) { $step = 1; $click_times++; } else { $step++; } }); const twitchVideoQualityInterval = setInterval(() => { try { let url = document.URL; let video = document.querySelector("video"); if (url != $url || is_resolution_changed(video)) { // multi clicks check if ($click_times == 1) { $click_times = 0; $url = url; $delay = 0; } else { if ($delay < 200) { $delay++; } else { if ($step == 1) { let settings_button = document.querySelector('button[data-a-target="player-settings-button"]'); if (settings_button) { simpleClick(settings_button, 1); } } if ($step == 2) { let quality_button = document.querySelector('button[data-a-target="player-settings-menu-item-quality"]'); if (quality_button) { simpleClick(quality_button, 2); } } if ($step == 3) { let inputs = document.querySelectorAll('input[name="player-settings-submenu-quality-option"]'); let input = get_best_quality_input(inputs); if (input) { simpleClick(input, 3); } } if ($step == 4) { let main_menu = document.querySelector('button[data-test-selector="main-menu"]'); if (main_menu) { simpleClick(main_menu, 4); } } if ($step == 5) { let menuitem = document.querySelector('button[role="menuitem"]'); if (menuitem) { simpleClick(menuitem, 5); console.warn("AUTO BEST RESOLUTION!"); } } } } } } catch (error) { console.warn(error); } }, 1); const is_resolution_changed = (video) => { let h = video.videoHeight; return h != $video_height; } const get_best_quality_input = (inputs) => { for (let i = 0; i < inputs.length; i++) { let input = inputs[i]; let span = input.nextSibling.querySelector('span'); if (span) { if (input.hasAttribute("DISABLED")) { i++; } let height = input.nextSibling.children[0].children[0].innerText; height = height.split("p")[0]; $video_height = height; return inputs[i]; } } } const is_video_playing = (video) => { if (video.currentTime > 0 && !video.paused && !video.ended && video.readyState > 2) { return true; } return false; }