您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
allows you to set different volumes for different twitch channels!
当前为
// ==UserScript== // @name volume set per channel // @namespace http://tampermonkey.net/ // @version 2025-07-29 // @description allows you to set different volumes for different twitch channels! // @author trevrosa // @run-at document-body // @match https://www.twitch.tv/* // @icon https://www.google.com/s2/favicons?sz=64&domain=twitch.tv // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== function log(msg) { console.log(`volumeset: ${msg}`) } // https://stackoverflow.com/a/61511955 function waitForElem(selector) { return new Promise(resolve => { if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } const observer = new MutationObserver(mutations => { if (document.querySelector(selector)) { observer.disconnect(); resolve(document.querySelector(selector)); } }); // If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336 observer.observe(document.body, { childList: true, subtree: true }); }); } (function() { 'use strict'; let lastPage = window.location.pathname; // https://twitch.tv/xdd // ^ three `/`s, 4 split regions if (window.location.toString().split("/").length != 4) { return; } function setVolume(slider) { const volume = GM_getValue(window.location.pathname, null); if (!volume) { return; } // change the slider's value to what we want slider.value = volume; // invoke the react event handler to then change the volume (https://stackoverflow.com/a/77083516) const reactHandlerKey = Object.keys(slider).find(key => key.startsWith('__reactProps$')); // changed to reactProps const changeEvent = new Event('change', { bubbles: true }); Object.defineProperty(changeEvent, 'currentTarget', {writable: false, value: slider}); // https://stackoverflow.com/a/49122553 slider[reactHandlerKey].onChange(changeEvent); log(`set the volume to ${volume} (${window.location.pathname})`) } log("waiting for volume slider") waitForElem("input[type='range']").then((slider) => { slider.onchange = (e) => { const volume = parseFloat(e.target.value); GM_setValue(window.location.pathname, volume) log(`${window.location.pathname} saved to ${volume} volume`); } log("set volume slider listener"); setVolume(slider); }) setInterval(() => { const newPage = window.location.pathname; if (newPage == lastPage) { return; } else { lastPage = newPage; setVolume(document.querySelector("input[type='range']")); } }, 500); })();