Instagram Volume Control Enhanced

Adjust default volume on Instagram videos with a user-friendly interface and persistent settings

目前為 2024-06-22 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Instagram Volume Control Enhanced
// @namespace    https://gf.qytechs.cn/fr/scripts/498295-instagram-volume-control-enhanced
// @version      1.3
// @description  Adjust default volume on Instagram videos with a user-friendly interface and persistent settings
// @author       Manu OVG
// @match        https://www.instagram.com/*
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const DEFAULT_VOLUME = 0.3;
    const VOLUME_STORAGE_KEY = 'instagram_volume';
    const SPEED_STORAGE_KEY = 'instagram_speed';
    const DEFAULT_SPEED = 1.0;

    function getStoredValue(key, defaultValue) {
        const storedValue = localStorage.getItem(key);
        return storedValue !== null ? parseFloat(storedValue) : defaultValue;
    }

    function setStoredValue(key, value) {
        localStorage.setItem(key, value);
    }

    function setVolume(volume) {
        const videos = document.querySelectorAll('video');
        videos.forEach(video => {
            video.volume = volume;
        });
    }

    function setSpeed(speed) {
        const videos = document.querySelectorAll('video');
        videos.forEach(video => {
            video.playbackRate = speed;
        });
    }

    function createVolumeControlUI() {
        const controlContainer = document.createElement('div');
        controlContainer.style.position = 'fixed';
        controlContainer.style.top = '60px'; // Moved down by 50px
        controlContainer.style.right = '10px';
        controlContainer.style.zIndex = '9999';
        controlContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
        controlContainer.style.color = '#fff';
        controlContainer.style.padding = '10px';
        controlContainer.style.borderRadius = '5px';
        controlContainer.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.5)';
        controlContainer.style.display = 'flex';
        controlContainer.style.alignItems = 'center';
        controlContainer.style.transition = 'opacity 0.3s';
        controlContainer.style.opacity = '0.8';

        const volumeIcon = document.createElement('span');
        volumeIcon.innerHTML = '🔊';
        volumeIcon.style.marginRight = '10px';

        const volumeLabel = document.createElement('label');
        volumeLabel.innerText = 'Volume:';
        volumeLabel.style.marginRight = '10px';

        const volumeSlider = document.createElement('input');
        volumeSlider.type = 'range';
        volumeSlider.min = '0';
        volumeSlider.max = '1';
        volumeSlider.step = '0.01';
        volumeSlider.value = getStoredValue(VOLUME_STORAGE_KEY, DEFAULT_VOLUME);
        volumeSlider.style.verticalAlign = 'middle';
        volumeSlider.style.transition = 'background-color 0.3s';
        volumeSlider.style.backgroundColor = '#ff0';
        volumeSlider.style.borderRadius = '5px';

        volumeSlider.addEventListener('input', () => {
            const volume = parseFloat(volumeSlider.value);
            setStoredValue(VOLUME_STORAGE_KEY, volume);
            setVolume(volume);
            controlContainer.style.backgroundColor = `rgba(0, ${Math.round(volume * 255)}, 0, 0.7)`;
        });

        const speedLabel = document.createElement('label');
        speedLabel.innerText = 'Speed:';
        speedLabel.style.marginLeft = '20px';
        speedLabel.style.marginRight = '10px';

        const speedSelect = document.createElement('select');
        const speeds = [0.5, 1, 1.5, 2];
        speeds.forEach(speed => {
            const option = document.createElement('option');
            option.value = speed;
            option.innerText = `${speed}x`;
            if (speed === getStoredValue(SPEED_STORAGE_KEY, DEFAULT_SPEED)) {
                option.selected = true;
            }
            speedSelect.appendChild(option);
        });

        speedSelect.addEventListener('change', () => {
            const speed = parseFloat(speedSelect.value);
            setStoredValue(SPEED_STORAGE_KEY, speed);
            setSpeed(speed);
        });

        const resetButton = document.createElement('button');
        resetButton.innerText = 'Reset';
        resetButton.style.marginLeft = '10px';
        resetButton.style.backgroundColor = '#fff';
        resetButton.style.color = '#000';
        resetButton.style.border = 'none';
        resetButton.style.borderRadius = '3px';
        resetButton.style.padding = '5px 10px';
        resetButton.style.cursor = 'pointer';
        resetButton.style.transition = 'background-color 0.3s';

        resetButton.addEventListener('click', () => {
            volumeSlider.value = DEFAULT_VOLUME;
            setStoredValue(VOLUME_STORAGE_KEY, DEFAULT_VOLUME);
            setVolume(DEFAULT_VOLUME);

            speedSelect.value = DEFAULT_SPEED;
            setStoredValue(SPEED_STORAGE_KEY, DEFAULT_SPEED);
            setSpeed(DEFAULT_SPEED);

            controlContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
        });

        resetButton.addEventListener('mouseover', () => {
            resetButton.style.backgroundColor = '#ddd';
        });

        resetButton.addEventListener('mouseout', () => {
            resetButton.style.backgroundColor = '#fff';
        });

        controlContainer.appendChild(volumeIcon);
        controlContainer.appendChild(volumeLabel);
        controlContainer.appendChild(volumeSlider);
        controlContainer.appendChild(speedLabel);
        controlContainer.appendChild(speedSelect);
        controlContainer.appendChild(resetButton);
        document.body.appendChild(controlContainer);

        controlContainer.addEventListener('mouseover', () => {
            controlContainer.style.opacity = '1';
        });

        controlContainer.addEventListener('mouseout', () => {
            controlContainer.style.opacity = '0.8';
        });

        // Set initial volume and speed based on stored values or defaults
        setVolume(getStoredValue(VOLUME_STORAGE_KEY, DEFAULT_VOLUME));
        setSpeed(getStoredValue(SPEED_STORAGE_KEY, DEFAULT_SPEED));
    }

    window.addEventListener('load', () => {
        createVolumeControlUI();

        // Observe changes to the DOM to handle new video elements
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                if (mutation.addedNodes.length) {
                    mutation.addedNodes.forEach(node => {
                        if (node.tagName === 'VIDEO' || (node.querySelectorAll && node.querySelectorAll('video').length > 0)) {
                            setTimeout(() => {
                                const videos = node.tagName === 'VIDEO' ? [node] : node.querySelectorAll('video');
                                videos.forEach(video => {
                                    video.volume = getStoredValue(VOLUME_STORAGE_KEY, DEFAULT_VOLUME);
                                    video.playbackRate = getStoredValue(SPEED_STORAGE_KEY, DEFAULT_SPEED);
                                });
                            }, 500); // Delay to ensure the video element is ready
                        }
                    });
                }
            });
        });

        observer.observe(document.body, { childList: true, subtree: true });
    });
})();

QingJ © 2025

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