音量增强器

增强页面音视频音量

目前為 2022-06-19 提交的版本,檢視 最新版本

// ==UserScript==
// @name         音量增强器
// @name:en-US   Volume Booster
// @namespace    System233
// @version      0.1
// @description   增强页面音视频音量
// @description:en-US  Increase page audio and video volume
// @author       System233
// @match        *://*/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bilibili.com
// @grant        none
// @license      GPL-3.0-only
// ==/UserScript==

// Copyright (c) 2022 System233
// 
// This software is released under the GPL-3.0 License.
// https://opensource.org/licenses/GPL-3.0



(function () {
    'use strict';

    const setup = () => {
        // /** @type {('Control'|'Shift'|'Alt')[]} */
        const hotKeys = {
            Control: true,
            Shift: false,
            Alt: true,
        };
        /** @type {(HTMLVideoElement|HTMLAudioElement)[]} */
        const nodes = [...document.querySelectorAll('video,audio')];
        nodes.forEach(node => {
            const audioCtx = new AudioContext();
            const gainNode = audioCtx.createGain();
            const mediaSource = audioCtx.createMediaElementSource(node);
            gainNode.connect(audioCtx.destination);
            mediaSource.connect(gainNode);
            let volume = 1;
            Object.defineProperty(node, 'volumeBoost', {
                get() {
                    return volume;
                },
                set(value) {
                    volume = Math.max(value,0);
                    gainNode.gain.setValueAtTime(volume, audioCtx.currentTime);
                }
            })
        });
        let index = 0;
        let active = false;
        let cleanupHandler = null;
        const current = {
            Control: false,
            Shift: false,
            Alt: false,
        }
        const length = nodes.length;
        const cleanup = () => {
            if (cleanupHandler != null) {
                cleanupHandler();
                cleanupHandler = null;
            }
        }
        const keys = Object.keys(current);
        const check = () => keys.findIndex(x => current[x] != hotKeys[x]) == -1;
        const updateSelector = () => {
            active = check();
            cleanup();
            if (active) {
                focusOn(index);
                updateText(true);
                
            }else{
                updateText(false);
            }
        }
        const focusOn = (direction) => {
            index = (index + length + direction) % length;
            const node = nodes[index];
            const { border, boxSizing } = node.style;
            node.style.border = '.5em solid red';
            node.style.boxSizing = 'border-box';
            const rect = node.getBoundingClientRect();
            if (rect.top + rect.height > window.innerHeight
                || rect.top < 0
                || rect.left < 0
                || rect.left + rect.width > window.innerWidth) {
                node.scrollIntoView();
            }
            cleanupHandler = () => {
                node.style.border = border;
                node.style.boxSizing = boxSizing;
            };
        }
        const updateText=(show)=>{
            const META_KEY='VolumeBooster';
            const node = nodes[index];
            if(!show){
                const el=Reflect.get(node,META_KEY);
                if(el){
                    el.remove();
                }
                return;
            }
            /** @type {HTMLDivElement} */
            const volumeBooster=Reflect.get(node,META_KEY)||document.createElement('div');
            volumeBooster.style.color='red';
            volumeBooster.style.position= 'absolute';
            volumeBooster.style.right=0;
            volumeBooster.style.background= '#ccc';
            volumeBooster.style.padding='0.2em';
            volumeBooster.style.zIndex=10000;
            volumeBooster.innerHTML=`${Math.round(node.volumeBoost*100)}%`;
            if(!volumeBooster.parentNode){
                node.parentNode.append(volumeBooster);
                Reflect.set(node,META_KEY,volumeBooster);
            }
        }
        const boost = (step) => {
            const node = nodes[index];
            node.volumeBoost += step;
            updateText(true);
        }
        const press = (key, press) => {
            if (key in current) {
                current[key] = press
            }
            updateSelector();
        }
        if(length){
            document.addEventListener('keyup', e => press(e.key, false));
            document.addEventListener('keydown', e => press(e.key, true));
            document.addEventListener('keydown', e => {
                if (active) {
                    switch (e.key) {
                        case 'ArrowUp': boost(.1); break;
                        case 'ArrowDown': boost(-.1); break;
                        case 'ArrowLeft': focusOn(-1); break;
                        case 'ArrowRight': focusOn(1); break;
                    }
                }
            })
        }
    }
    window.addEventListener('load', setup);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址