Skip to content

Instantly share code, notes, and snippets.

@Vivelin
Last active June 9, 2022 06:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Vivelin/2321d17bf26016ceaed87d6d1a281881 to your computer and use it in GitHub Desktop.
Save Vivelin/2321d17bf26016ceaed87d6d1a281881 to your computer and use it in GitHub Desktop.
YouTube audio compressor
// ==UserScript==
// @name YouTube audio compressor
// @namespace https://vivelin.net/
// @version 0.4
// @description Adds an audio compressor option to YouTube videos.
// @author Vivelin
// @match https://*.youtube.com/*
// @updateURL https://gist.github.com/Vivelin/2321d17bf26016ceaed87d6d1a281881/raw/YouTube%2520audio%2520compressor.user.js
// @run-at document-idle
// @grant none
// ==/UserScript==
let _vivelin__audioContext = null;
let _vivelin__source = null;
let _vivelin_compressor = null;
let _vivelin_compressorMenuItem = null;
function createCompressorMenuItem() {
const menuItem = document.createElement('div');
menuItem.className = 'ytp-menuitem';
menuItem.setAttribute('role', 'menuitemcheckbox');
menuItem.setAttribute('aria-checked', window._isCompressorActive || false);
menuItem.tabIndex = 0;
const icon = document.createElement('div');
icon.className = 'ytp-menuitem-icon';
menuItem.appendChild(icon);
const label = document.createElement('div');
label.className = 'ytp-menuitem-label';
label.textContent = 'Compressor';
menuItem.appendChild(label);
const content = document.createElement('div');
content.className = 'ytp-menuitem-content';
const toggleCheckbox = document.createElement('div');
toggleCheckbox.className = 'ytp-menuitem-toggle-checkbox';
content.appendChild(toggleCheckbox);
menuItem.appendChild(content);
console.log(menuItem);
return menuItem;
}
function setupCompressor(player, ytpPanelMenu) {
if (!_vivelin__audioContext) {
_vivelin__audioContext = new AudioContext();
}
if (!_vivelin__source) {
_vivelin__source = _vivelin__audioContext.createMediaElementSource(player);
_vivelin__source.connect(_vivelin__audioContext.destination);
}
if (!_vivelin_compressor) {
_vivelin_compressor = _vivelin__audioContext.createDynamicsCompressor();
_vivelin_compressor.threshold.setValueAtTime(-50, _vivelin__audioContext.currentTime);
_vivelin_compressor.knee.setValueAtTime(40, _vivelin__audioContext.currentTime);
_vivelin_compressor.ratio.setValueAtTime(12, _vivelin__audioContext.currentTime);
_vivelin_compressor.attack.setValueAtTime(0, _vivelin__audioContext.currentTime);
_vivelin_compressor.release.setValueAtTime(0.25, _vivelin__audioContext.currentTime);
}
if (!_vivelin_compressorMenuItem) {
_vivelin_compressorMenuItem = createCompressorMenuItem();
ytpPanelMenu.appendChild(_vivelin_compressorMenuItem);
_vivelin_compressorMenuItem.onclick = function () {
const isActive = _vivelin_compressorMenuItem.getAttribute('aria-checked');
if (isActive === 'false') {
window._isCompressorActive = true;
_vivelin_compressorMenuItem.setAttribute('aria-checked', 'true');
_vivelin__source.disconnect(_vivelin__audioContext.destination);
_vivelin__source.connect(_vivelin_compressor);
_vivelin_compressor.connect(_vivelin__audioContext.destination);
}
else {
window._isCompressorActive = false;
_vivelin_compressorMenuItem.setAttribute('aria-checked', 'false');
_vivelin__source.disconnect(_vivelin_compressor);
_vivelin_compressor.disconnect(_vivelin__audioContext.destination);
_vivelin__source.connect(_vivelin__audioContext.destination);
}
};
}
}
function startSetup() {
const player = document.querySelector('#ytd-player video');
const ytpPanelMenu = document.querySelector('#ytd-player .ytp-settings-menu .ytp-panel-menu');
if (player && ytpPanelMenu) {
setupCompressor(player, ytpPanelMenu);
console.info('Compressor option added', window._isCompressorActive);
return true;
}
return false;
}
function trySetup() {
console.debug('Polling for player...');
const intervalId = window.setInterval(function () {
if (startSetup()) {
window.clearInterval(intervalId);
}
}, 100);
const cancelId = window.setTimeout(function () {
window.clearInterval(intervalId);
}, 10000);
}
if (!startSetup()) {
trySetup();
window.addEventListener('yt-navigate-finish', function () {
trySetup();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment