Greasy Fork

Greasy Fork is available in English.

通用音量增强器 - Universal Volume Booster

在所有网站(包括YouTube和TikTok)上强制增强音量,支持Ctrl+Alt+↑/↓/W/S快捷键,最高可增强10倍

当前为 2025-05-24 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         通用音量增强器 - Universal Volume Booster
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  在所有网站(包括YouTube和TikTok)上强制增强音量,支持Ctrl+Alt+↑/↓/W/S快捷键,最高可增强10倍
// @author       醉春风制作
// @match        *://*/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @run-at       document-start
// @license      All Rights Reserved
// ==/UserScript==

/*
通用音量增强器 - Universal Volume Booster
版本: 1.5
作者: 醉春风制作

版权所有 (c) 2025 醉春风制作

保留所有权利。

本脚本为作者独立创作,未经作者明确授权,禁止任何形式的:
1. 复制、修改或二次开发本脚本
2. 重新发布、分发或出售本脚本
3. 移除或修改本脚本中的版权信息和作者信息

使用本脚本即表示您同意遵守上述条款。
*/

(function() {
    'use strict';
    
    // 保存用户设置的音量增强倍数
    let volumeMultiplier = GM_getValue('volumeMultiplier', 1.0);
    let isBoosterActive = GM_getValue('isBoosterActive', false);
    let isDragging = false;
    let controlsVisible = false;
    let hideTimeout;
    let lastKeyTime = 0; // 用于防止快捷键重复触发
    let mediaElements = []; // 跟踪页面中的所有媒体元素
    
    // 创建音量增强控制界面
    function createVolumeControls() {
        // 添加样式
        GM_addStyle(`
            #volume-booster-container {
                position: fixed;
                top: 20px;
                right: 20px;
                background-color: rgba(0, 0, 0, 0.7);
                color: white;
                padding: 10px;
                border-radius: 5px;
                z-index: 9999999;
                font-family: Arial, sans-serif;
                transition: opacity 0.3s ease;
                box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
                user-select: none;
                opacity: 0;
                pointer-events: none;
            }
            #volume-booster-container.visible {
                opacity: 1;
                pointer-events: auto;
            }
            #volume-booster-container.active {
                border: 2px solid #4CAF50;
            }
            #volume-booster-container.inactive {
                border: 2px solid #F44336;
            }
            #volume-slider-container {
                width: 200px;
                margin: 10px 0;
            }
            #volume-slider {
                width: 100%;
                height: 5px;
                -webkit-appearance: none;
                background: linear-gradient(to right, #4CAF50 0%, #4CAF50 ${(volumeMultiplier-1)*100/9}%, #ddd ${(volumeMultiplier-1)*100/9}%, #ddd 100%);
                outline: none;
                border-radius: 5px;
            }
            #volume-slider::-webkit-slider-thumb {
                -webkit-appearance: none;
                width: 15px;
                height: 15px;
                border-radius: 50%;
                background: white;
                cursor: pointer;
                box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
            }
            #volume-slider::-moz-range-thumb {
                width: 15px;
                height: 15px;
                border-radius: 50%;
                background: white;
                cursor: pointer;
                box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
                border: none;
            }
            #volume-value {
                text-align: center;
                font-size: 14px;
                margin-top: 5px;
            }
            #volume-toggle {
                width: 100%;
                padding: 5px;
                background-color: #4CAF50;
                color: white;
                border: none;
                border-radius: 3px;
                cursor: pointer;
                font-size: 14px;
                margin-top: 5px;
            }
            #volume-toggle.inactive {
                background-color: #F44336;
            }
            .volume-booster-title {
                font-size: 14px;
                text-align: center;
                margin-bottom: 5px;
                font-weight: bold;
            }
            .volume-booster-shortcut {
                font-size: 12px;
                text-align: center;
                margin-top: 5px;
                color: #aaa;
            }
            #volume-status-indicator {
                position: fixed;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                background-color: rgba(0, 0, 0, 0.7);
                color: white;
                padding: 15px 20px;
                border-radius: 5px;
                font-size: 16px;
                z-index: 9999999;
                opacity: 0;
                transition: opacity 0.3s ease;
                pointer-events: none;
                text-align: center;
            }
            #volume-status-indicator.visible {
                opacity: 1;
            }
        `);
        
        // 创建控制界面
        const container = document.createElement('div');
        container.id = 'volume-booster-container';
        container.className = isBoosterActive ? 'active' : 'inactive';
        
        container.innerHTML = `
            <div class="volume-booster-title">音量增强器 - 醉春风制作</div>
            <div id="volume-slider-container">
                <input type="range" id="volume-slider" min="1" max="10" step="0.1" value="${volumeMultiplier}">
                <div id="volume-value">增强倍数: ${volumeMultiplier.toFixed(1)}x</div>
            </div>
            <button id="volume-toggle" class="${isBoosterActive ? '' : 'inactive'}">${isBoosterActive ? '已启用' : '已禁用'}</button>
            <div class="volume-booster-shortcut">快捷键: Ctrl+Alt+↑/↓ Ctrl+Alt+W/S</div>
        `;
        
        document.body.appendChild(container);
        
        // 创建状态指示器
        const statusIndicator = document.createElement('div');
        statusIndicator.id = 'volume-status-indicator';
        document.body.appendChild(statusIndicator);
        
        // 添加事件监听
        const slider = document.getElementById('volume-slider');
        const toggle = document.getElementById('volume-toggle');
        
        slider.addEventListener('input', function() {
            volumeMultiplier = parseFloat(this.value);
            document.getElementById('volume-value').textContent = `增强倍数: ${volumeMultiplier.toFixed(1)}x`;
            this.style.background = `linear-gradient(to right, #4CAF50 0%, #4CAF50 ${(volumeMultiplier-1)*100/9}%, #ddd ${(volumeMultiplier-1)*100/9}%, #ddd 100%)`;
            
            // 保存设置
            GM_setValue('volumeMultiplier', volumeMultiplier);
            
            applyVolumeBoost();
        });
        
        toggle.addEventListener('click', function() {
            toggleBooster();
        });
        
        // 鼠标悬停显示控制界面
        container.addEventListener('mouseenter', function() {
            clearTimeout(hideTimeout);
        });
        
        container.addEventListener('mouseleave', function() {
            if (!isDragging) {
                hideTimeout = setTimeout(() => {
                    hideControls();
                }, 2000);
            }
        });
        
        return container;
    }
    
    // 显示状态消息
    function showStatusMessage(message) {
        const statusIndicator = document.getElementById('volume-status-indicator');
        if (!statusIndicator) return;
        
        statusIndicator.textContent = message;
        statusIndicator.classList.add('visible');
        
        setTimeout(() => {
            statusIndicator.classList.remove('visible');
        }, 1500);
    }
    
    // 显示控制界面
    function showControls() {
        clearTimeout(hideTimeout);
        if (!document.getElementById('volume-booster-container')) {
            createVolumeControls();
        }
        
        const container = document.getElementById('volume-booster-container');
        container.classList.add('visible');
        controlsVisible = true;
        
        hideTimeout = setTimeout(() => {
            hideControls();
        }, 3000);
    }
    
    // 隐藏控制界面
    function hideControls() {
        if (!isDragging) {
            const container = document.getElementById('volume-booster-container');
            if (container) {
                container.classList.remove('visible');
                controlsVisible = false;
            }
        }
    }
    
    // 应用音量增强
    function applyVolumeBoost() {
        // 获取所有媒体元素
        mediaElements = [...document.querySelectorAll('video, audio')];
        
        // 特殊处理YouTube和TikTok
        const isYouTube = window.location.hostname.includes('youtube.com');
        const isTikTok = window.location.hostname.includes('tiktok.com');
        
        mediaElements.forEach(media => {
            // 保存原始音量
            if (media.dataset.originalVolume === undefined) {
                media.dataset.originalVolume = media.volume;
            }
            
            // 应用或恢复音量
            if (isBoosterActive) {
                // 使用 AudioContext 增强音量
                setupAudioBooster(media, isYouTube, isTikTok);
            } else {
                // 恢复原始音量
                if (media.dataset.originalVolume !== undefined) {
                    media.volume = parseFloat(media.dataset.originalVolume);
                }
                
                // 断开音频处理节点
                if (media.boosterSource) {
                    try {
                        media.boosterSource.disconnect();
                        media.boosterGain.disconnect();
                        media.boosterSource = null;
                        media.boosterGain = null;
                        media.boosterContext = null;
                    } catch (e) {
                        console.log('断开音频节点失败:', e);
                    }
                }
            }
        });
    }
    
    // 使用 AudioContext 设置音量增强
    function setupAudioBooster(mediaElement, isYouTube, isTikTok) {
        if (!mediaElement.boosterContext) {
            try {
                const AudioContext = window.AudioContext || window.webkitAudioContext;
                const context = new AudioContext();
                const source = context.createMediaElementSource(mediaElement);
                const gainNode = context.createGain();
                
                source.connect(gainNode);
                gainNode.connect(context.destination);
                
                mediaElement.boosterContext = context;
                mediaElement.boosterSource = source;
                mediaElement.boosterGain = gainNode;
            } catch (e) {
                console.log('创建音频处理节点失败:', e);
                // 备用方案:直接修改音量属性
                if (isYouTube || isTikTok) {
                    // 对于YouTube和TikTok,使用备用方案
                    try {
                        const originalVolume = parseFloat(mediaElement.dataset.originalVolume) || 0.5;
                        // 确保不超过1.0
                        mediaElement.volume = Math.min(1.0, originalVolume * volumeMultiplier);
                    } catch (err) {
                        console.log('备用音量调整失败:', err);
                    }
                }
                return;
            }
        }
        
        if (mediaElement.boosterGain) {
            mediaElement.boosterGain.gain.value = volumeMultiplier;
        }
    }
    
    // 增加音量
    function increaseVolume() {
        // 如果未启用,则启用
        if (!isBoosterActive) {
            enableBooster();
        }
        
        // 增加音量倍数
        volumeMultiplier = Math.min(10, volumeMultiplier + 0.1);
        GM_setValue('volumeMultiplier', volumeMultiplier);
        
        // 更新滑块
        if (document.getElementById('volume-slider')) {
            document.getElementById('volume-slider').value = volumeMultiplier;
            document.getElementById('volume-value').textContent = `增强倍数: ${volumeMultiplier.toFixed(1)}x`;
            document.getElementById('volume-slider').style.background = `linear-gradient(to right, #4CAF50 0%, #4CAF50 ${(volumeMultiplier-1)*100/9}%, #ddd ${(volumeMultiplier-1)*100/9}%, #ddd 100%)`;
        }
        
        applyVolumeBoost();
        showControls();
        
        // 显示状态提示
        showStatusMessage(`音量增强: ${volumeMultiplier.toFixed(1)}x`);
    }
    
    // 减少音量
    function decreaseVolume() {
        // 减少音量倍数
        volumeMultiplier = Math.max(1, volumeMultiplier - 0.1);
        GM_setValue('volumeMultiplier', volumeMultiplier);
        
        // 更新滑块
        if (document.getElementById('volume-slider')) {
            document.getElementById('volume-slider').value = volumeMultiplier;
            document.getElementById('volume-value').textContent = `增强倍数: ${volumeMultiplier.toFixed(1)}x`;
            document.getElementById('volume-slider').style.background = `linear-gradient(to right, #4CAF50 0%, #4CAF50 ${(volumeMultiplier-1)*100/9}%, #ddd ${(volumeMultiplier-1)*100/9}%, #ddd 100%)`;
        }
        
        applyVolumeBoost();
        showControls();
        
        // 显示状态提示
        showStatusMessage(`音量增强: ${volumeMultiplier.toFixed(1)}x`);
    }
    
    // 启用音量增强器
    function enableBooster() {
        isBoosterActive = true;
        GM_setValue('isBoosterActive', true);
        
        if (document.getElementById('volume-toggle')) {
            document.getElementById('volume-toggle').textContent = '已启用';
            document.getElementById('volume-toggle').className = '';
            document.getElementById('volume-booster-container').className = 'visible active';
        }
        
        applyVolumeBoost();
        showStatusMessage('音量增强已启用');
    }
    
    // 禁用音量增强器
    function disableBooster() {
        isBoosterActive = false;
        GM_setValue('isBoosterActive', false);
        
        if (document.getElementById('volume-toggle')) {
            document.getElementById('volume-toggle').textContent = '已禁用';
            document.getElementById('volume-toggle').className = 'inactive';
            document.getElementById('volume-booster-container').className = 'visible inactive';
        }
        
        applyVolumeBoost(); // 这会恢复原始音量
        showStatusMessage('音量增强已禁用');
    }
    
    // 切换音量增强器状态
    function toggleBooster() {
        if (isBoosterActive) {
            disableBooster();
        } else {
            enableBooster();
        }
    }
    
    // 切换控制面板显示状态
    function toggleControlPanel() {
        if (controlsVisible) {
            hideControls();
        } else {
            showControls();
        }
    }
    
    // 增强的快捷键检测函数
    function isUpArrowWithCtrlAlt(e) {
        // 多重检测方法确保兼容性
        return e.ctrlKey && e.altKey && (
            e.keyCode === 38 || 
            e.which === 38 || 
            e.code === 'ArrowUp' || 
            e.key === 'ArrowUp' || 
            e.key === 'Up' ||
            e.key === '↑'
        );
    }
    
    function isDownArrowWithCtrlAlt(e) {
        return e.ctrlKey && e.altKey && (
            e.keyCode === 40 || 
            e.which === 40 || 
            e.code === 'ArrowDown' || 
            e.key === 'ArrowDown' || 
            e.key === 'Down' ||
            e.key === '↓'
        );
    }
    
    function isWKeyWithCtrlAlt(e) {
        return e.ctrlKey && e.altKey && (
            e.keyCode === 87 ||
            e.which === 87 ||
            e.code === 'KeyW' ||
            e.key === 'w' ||
            e.key === 'W'
        );
    }
    
    function isSKeyWithCtrlAlt(e) {
        return e.ctrlKey && e.altKey && (
            e.keyCode === 83 ||
            e.which === 83 ||
            e.code === 'KeyS' ||
            e.key === 's' ||
            e.key === 'S'
        );
    }
    
    // 设置键盘监听
    function setupKeyboardListeners() {
        document.addEventListener('keydown', function(e) {
            const now = Date.now();
            if (now - lastKeyTime < 200) return;
            
            if (isUpArrowWithCtrlAlt(e)) {
                e.preventDefault();
                e.stopPropagation();
                lastKeyTime = now;
                increaseVolume();
                return false;
            }
            
            if (isDownArrowWithCtrlAlt(e)) {
                e.preventDefault();
                e.stopPropagation();
                lastKeyTime = now;
                decreaseVolume();
                return false;
            }
            
            if (isWKeyWithCtrlAlt(e)) {
                e.preventDefault();
                e.stopPropagation();
                lastKeyTime = now;
                enableBooster();
                return false;
            }
            
            if (isSKeyWithCtrlAlt(e)) {
                e.preventDefault();
                e.stopPropagation();
                lastKeyTime = now;
                disableBooster();
                return false;
            }
        }, true);
    }
    
    // 监听新添加的媒体元素
    function setupMediaObserver() {
        const observer = new MutationObserver(mutations => {
            let mediaAdded = false;
            
            mutations.forEach(mutation => {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeName === 'VIDEO' || node.nodeName === 'AUDIO') {
                        mediaAdded = true;
                    } else if (node.nodeType === 1) {
                        const mediaElements = node.querySelectorAll('video, audio');
                        if (mediaElements.length > 0) {
                            mediaAdded = true;
                        }
                    }
                });
            });
            
            if (mediaAdded && isBoosterActive) {
                applyVolumeBoost();
            }
        });
        
        // 开始观察DOM变化
        if (document.body) {
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        }
        
        return observer;
    }
    
    // 初始化音量增强器
    function initializeVolumeBooster() {
        // 创建控制界面但不显示
        createVolumeControls();
        
        // 设置键盘监听
        setupKeyboardListeners();
        
        // 设置媒体观察器
        setupMediaObserver();
        
        // 应用音量增强
        if (isBoosterActive) {
            applyVolumeBoost();
        }
    }
    
    // 如果页面已经加载完成,立即初始化
    if (document.readyState === 'complete' || document.readyState === 'interactive') {
        // 延迟一点以确保DOM已准备好
        setTimeout(function() {
            if (document.body) {
                initializeVolumeBooster();
            }
        }, 100);
    } else {
        // 否则等待DOMContentLoaded事件
        window.addEventListener('DOMContentLoaded', function() {
            setTimeout(function() {
                initializeVolumeBooster();
            }, 100);
        });
    }
    
    // 立即设置键盘监听,不等待页面加载
    setupKeyboardListeners();
})();