// ==UserScript== // @name No Volume Normalization 4 YouTube // @namespace https://gist.github.com/abec2304 // @description Enjoy YouTube videos at their true volume // @author abec2304 // @version 4.0 // @match https://*.youtube.com/* // @match https://*.youtube-nocookie.com/* // @run-at document-start // @grant GM_addElement // @license AGPLv3 // @downloadURL none // ==/UserScript== function ytvt_hook() { function ytvt_patchDescriptor(targetProto, targetProp) { let desc = Object.getOwnPropertyDescriptor(targetProto, targetProp); Object.defineProperty(targetProto, targetProp, { enumerable: true, configurable: true, get: function() { return desc.get.call(this); }, set: function(e) { void e; } }); return desc; } let ytvt_desc = ytvt_patchDescriptor(HTMLMediaElement.prototype, 'volume'); let ytvt_valSetter = HTMLElement.prototype.setAttribute; HTMLElement.prototype.setAttribute = function(name, val) { if(name === 'aria-valuenow') { let isVolume = this.matches('[aria-label="Volume"][role="slider"]'); if(isVolume) { let player = document.querySelector('.video-stream'); let newVolume = val / 100; if(player && player.volume !== newVolume) { ytvt_desc.set.call(player, newVolume); } } } ytvt_valSetter.call(this, name, val); }; let ytvt_rule = '.ytp-sfn-content::after, ytmusic-nerd-stats::after { content: "using No Volume Normalization" }'; let ytvt_sheet = new CSSStyleSheet(); ytvt_sheet.insertRule(ytvt_rule); // push doesn't work here in Firefox for whatever reason, so use concat document.adoptedStyleSheets = (document.adoptedStyleSheets || []).concat([ytvt_sheet]); let ytvt_script = document.getElementById('ytvoltweak'); if(ytvt_script) { ytvt_script.remove(); } } function ytvt_inject() { let ytvt_textContent = ytvt_hook + '\n' + ytvt_hook.name + '();'; GM_addElement('script', {textContent: ytvt_textContent, id: 'ytvoltweak'}); } if(!document.head) { let ytvt_headObserver = new MutationObserver(function(_arr, obs) { if(document.head) { obs.disconnect(); ytvt_inject(); } }); ytvt_headObserver.observe(document, {subtree: true, childList: true}); } else { ytvt_inject(); }