视频加速器

网页中有视频时,右下角显示倍速操作界面,可隐藏为一个淡色圆形图标并显示倍速数字,显示操作界面时圆形图标隐藏。

目前为 2024-08-29 提交的版本。查看 最新版本

// ==UserScript==
// @name         视频加速器
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  网页中有视频时,右下角显示倍速操作界面,可隐藏为一个淡色圆形图标并显示倍速数字,显示操作界面时圆形图标隐藏。
// @license     MIT
// @author      失辛向南
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    let speedControlContainer;
    let speedSelect;
    let isVisible = false;
    let iconContainer;

    function createSpeedControlUI() {
        speedControlContainer = document.createElement('div');
        speedControlContainer.style.position = 'fixed';
        speedControlContainer.style.bottom = '20px';
        speedControlContainer.style.right = '20px';
        speedControlContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
        speedControlContainer.style.padding = '10px';
        speedControlContainer.style.borderRadius = '5px';
        speedControlContainer.style.color = 'white';
        speedControlContainer.style.zIndex = '9999';
        speedControlContainer.style.display = 'none';

        const speedLabel = document.createElement('span');
        speedLabel.textContent = 'Speed: ';
        speedControlContainer.appendChild(speedLabel);

        speedSelect = document.createElement('select');
        for (let i = 0.25; i <= 5; i += 0.25) {
            const option = document.createElement('option');
            option.value = i;
            option.textContent = i + 'x';
            speedSelect.appendChild(option);
        }
        speedSelect.value = '1';
        speedControlContainer.appendChild(speedSelect);

        document.body.appendChild(speedControlContainer);

        speedSelect.addEventListener('change', updateVideoSpeeds);

        // 创建图标容器
        iconContainer = document.createElement('div');
        iconContainer.style.position = 'fixed';
        iconContainer.style.bottom = '20px';
        iconContainer.style.right = '20px';
        iconContainer.style.width = '30px';
        iconContainer.style.height = '30px';
        iconContainer.style.backgroundColor = 'rgba(200, 200, 200, 0.5)';
        iconContainer.style.borderRadius = '50%';
        iconContainer.style.textAlign = 'center';
        iconContainer.style.lineHeight = '30px';
        iconContainer.style.cursor = 'pointer';
        iconContainer.style.zIndex = '9999';
        document.body.appendChild(iconContainer);

        iconContainer.addEventListener('click', toggleVisibility);

        document.addEventListener('mousemove', handleMouseMove);
    }

    function updateVideoSpeeds() {
        const videos = document.getElementsByTagName('video');
        for (let video of videos) {
            video.playbackRate = parseFloat(speedSelect.value);
        }
        updateIconText();
    }

    function checkForVideos() {
        const videos = document.getElementsByTagName('video');
        if (videos.length > 0) {
            if (!speedControlContainer) {
                createSpeedControlUI();
            }
            updateVideoSpeeds();
        } else {
            if (speedControlContainer) {
                speedControlContainer.remove();
                speedControlContainer = null;
                speedSelect = null;
                iconContainer.remove();
                iconContainer = null;
            }
        }
    }

    function isVideoPage() {
        const videoElements = document.getElementsByTagName('video');
        const videoTagsInHTML = document.documentElement.innerHTML.includes('<video');
        return videoElements.length > 0 || videoTagsInHTML;
    }

    function handleMouseMove(event) {
        if (!isVisible && isInsideIcon(event.clientX, event.clientY)) {
            showContainer();
        } else if (isVisible &&!isInsideContainer(event.clientX, event.clientY)) {
            hideContainer();
        }
    }

    function isInsideIcon(x, y) {
        const iconRect = iconContainer.getBoundingClientRect();
        return x >= iconRect.left && x <= iconRect.right && y >= iconRect.top && y <= iconRect.bottom;
    }

    function isInsideContainer(x, y) {
        const containerRect = speedControlContainer.getBoundingClientRect();
        return x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
    }

    function showContainer() {
        speedControlContainer.style.display = 'block';
        iconContainer.style.display = 'none';
        isVisible = true;
    }

    function hideContainer() {
        speedControlContainer.style.display = 'none';
        iconContainer.style.display = 'block';
        isVisible = false;
    }

    function toggleVisibility() {
        if (isVisible) {
            hideContainer();
        } else {
            showContainer();
        }
    }

    function updateIconText() {
        iconContainer.textContent = speedSelect.value + 'x';
    }

    window.addEventListener('load', () => {
        if (isVideoPage()) {
            checkForVideos();
        }
    });
    window.addEventListener('DOMContentLoaded', () => {
        if (isVideoPage()) {
            checkForVideos();
        }
    });
})();

QingJ © 2025

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