From c32e2283ce64760553d5840bd1d64383ae337597 Mon Sep 17 00:00:00 2001 From: joegauto Date: Sat, 11 Jul 2026 20:46:30 +0200 Subject: [PATCH] feat: add volume boost player button (fixes #4146 partially) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a Volume Boost button to the player controls that amplifies audio beyond 100% using the Web Audio API GainNode. - Click cycles through 1x → 2x → 3x → 1x - Button opacity indicates active state - Resets gain to 1x when disabled in settings - Toggle available under Player section in extension menu Addresses the 'Volume Boost' item from issue #4146 (Player buttons to be added). --- _locales/en/messages.json | 6 +++ js&css/web-accessible/core.js | 9 ++++ .../web-accessible/www.youtube.com/player.js | 49 +++++++++++++++++++ menu/skeleton-parts/player.js | 4 ++ 4 files changed, 68 insertions(+) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 686f493a0..8277c9ac9 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1110,6 +1110,9 @@ "player_rotate_button": { "message": "Rotate video" }, + "player_volume_boost_button": { + "message": "Volume Boost button" + }, "playerAutoPipOutside": { "message": "Auto-PiP only outside source Tab" }, @@ -1296,6 +1299,9 @@ "rotate": { "message": "Rotate" }, + "volumeBoost": { + "message": "Volume Boost" + }, "save": { "message": "Save" }, diff --git a/js&css/web-accessible/core.js b/js&css/web-accessible/core.js index c744c1625..3e90b0388 100644 --- a/js&css/web-accessible/core.js +++ b/js&css/web-accessible/core.js @@ -348,6 +348,15 @@ document.addEventListener('it-message-from-extension', function () { } break + case 'playerVolumeBoostButton': + if (ImprovedTube.storage.player_volume_boost_button === false) { + ImprovedTube.elements.buttons['it-volume-boost-button']?.remove(); + if (ImprovedTube.volumeBoostGain) { + ImprovedTube.volumeBoostGain.gain.value = 1; + } + } + break + case 'playerFitToWinButton': if (ImprovedTube.storage.player_fit_to_win_button === false) { ImprovedTube.elements.buttons['it-fit-to-win-player-button']?.remove(); diff --git a/js&css/web-accessible/www.youtube.com/player.js b/js&css/web-accessible/www.youtube.com/player.js index 0f8f47423..a56566f35 100644 --- a/js&css/web-accessible/www.youtube.com/player.js +++ b/js&css/web-accessible/www.youtube.com/player.js @@ -1094,6 +1094,55 @@ ImprovedTube.playerRotateButton = function () { } }; +/*------------------------------------------------------------------------------ +VOLUME BOOST BUTTON +------------------------------------------------------------------------------*/ +ImprovedTube.playerVolumeBoostButton = function () { + if (this.storage.player_volume_boost_button === true) { + var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'), + path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + + svg.setAttributeNS(null, 'viewBox', '0 0 24 24'); + path.setAttributeNS(null, 'd', 'M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z'); + + svg.appendChild(path); + + var button = this.createPlayerButton({ + id: 'it-volume-boost-button', + child: svg, + opacity: 0.5, + onclick: function () { + // ponytail: Web Audio API gain node. Ceiling: clipping at very high gain (>4x). Upgrade: add compressor node. + var video = ImprovedTube.elements.video; + if (!video) return; + + if (!ImprovedTube.volumeBoostContext) { + var AudioContext = window.AudioContext || window.webkitAudioContext; + ImprovedTube.volumeBoostContext = new AudioContext(); + ImprovedTube.volumeBoostSource = ImprovedTube.volumeBoostContext.createMediaElementSource(video); + ImprovedTube.volumeBoostGain = ImprovedTube.volumeBoostContext.createGain(); + ImprovedTube.volumeBoostSource.connect(ImprovedTube.volumeBoostGain); + ImprovedTube.volumeBoostGain.connect(ImprovedTube.volumeBoostContext.destination); + } + + var gain = ImprovedTube.volumeBoostGain.gain; + var current = gain.value; + + // Cycle: 1x → 2x → 3x → 1x + var next = current >= 3 ? 1 : current + 1; + gain.value = next; + + var btn = ImprovedTube.elements.buttons['it-volume-boost-button']; + if (btn) { + btn.style.opacity = next > 1 ? '1' : '0.5'; + btn.dataset.title = 'Volume Boost (' + next + 'x)'; + } + }, + title: 'Volume Boost (1x)' + }); + } +}; + /*------------------------------------------------------------------------------ PLAYBACK SPEED BUTTON ------------------------------------------------------------------------------*/ diff --git a/menu/skeleton-parts/player.js b/menu/skeleton-parts/player.js index b3880cef1..788b9327d 100644 --- a/menu/skeleton-parts/player.js +++ b/menu/skeleton-parts/player.js @@ -1722,6 +1722,10 @@ extension.skeleton.main.layers.section.player.on.click = { component: 'switch', text: 'rotate' }, + player_volume_boost_button: { + component: 'switch', + text: 'volumeBoost' + }, player_hamburger_button: { component: 'switch', text: 'Hamburger_Menu'