控制视频快进快退及倍速播放

使用鼠标滚轮控制视频播放进度

当前为 2024-12-22 提交的版本,查看 最新版本

// ==UserScript==
// @name         控制视频快进快退及倍速播放
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  使用鼠标滚轮控制视频播放进度
// @author       zwols
// @license      MIT
// @match        *://*/*
// @match        *://*.youtube.com/*
// @match        *://*.youku.com/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    // 等待视频元素加载
    const checkVideo = setInterval(() => {
        const video = document.querySelector('.html5-main-video, video, .youku-player video');
        if (video && video.readyState >= 2) {  // 确保视频已加载
            clearInterval(checkVideo);
            initVideoControl(video);
        }
    }, 1000);

    function initVideoControl(video) {
        if (video.dataset.controlInitialized) return;
        video.dataset.controlInitialized = 'true';
        
        // 获取视频容器
        const isYouku = window.location.hostname.includes('youku.com');
        const container = isYouku 
            ? document.querySelector('.youku-player')
            : (video.closest('#movie_player') || video.parentElement);
        
        if (!container) return;
        
        // 添加滚轮控制
        const wheelHandler = function(e) {
            e.preventDefault();
            e.stopPropagation();
            
            if (e.shiftKey) {
                // 调整播放速度
                const speedChange = 0.25;
                video.playbackRate = Math.min(4, Math.max(0.25, 
                    video.playbackRate + (e.deltaY < 0 ? speedChange : -speedChange)
                ));
                showSpeedIndicator(video, container);
            } else {
                // 调整播放进度
                const seekAmount = 5;
                video.currentTime = Math.min(video.duration, Math.max(0,
                    video.currentTime + (e.deltaY < 0 ? -seekAmount : seekAmount)
                ));
            }
            return false;
        };

        // 为优酷特别处理事件监听
        if (isYouku) {
            container.addEventListener('wheel', wheelHandler, { passive: false, capture: true });
        } else {
            video.addEventListener('wheel', wheelHandler, { passive: false });
        }

        addGuideBox(video, container);
    }

    function showSpeedIndicator(video, container) {
        let indicator = container.querySelector('.speed-indicator');
        
        if (!indicator) {
            indicator = document.createElement('div');
            indicator.className = 'speed-indicator';
            indicator.style.cssText = `
                position: absolute;
                top: 60px;
                right: 20px;
                background: rgba(0, 0, 0, 0.7);
                color: white;
                padding: 5px 10px;
                border-radius: 4px;
                font-size: 14px;
                z-index: 2147483647;
                pointer-events: none;
                opacity: 0;
                transition: opacity 0.3s;
            `;
            container.appendChild(indicator);
        }

        indicator.textContent = `${video.playbackRate.toFixed(2)}x`;
        indicator.style.opacity = '1';
        clearTimeout(indicator.fadeTimeout);
        indicator.fadeTimeout = setTimeout(() => indicator.style.opacity = '0', 2000);
    }

    function addGuideBox(video, container) {
        const guideBox = document.createElement('div');
        guideBox.className = 'video-control-guide';
        guideBox.style.cssText = `
            position: fixed;
            left: 10px;
            top: 50%;
            transform: translateY(-50%) translateX(-150px);
            background: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 15px;
            border-radius: 8px;
            font-size: 13px;
            z-index: 2147483647;
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
            opacity: 0;
            transition: all 0.3s ease;
            border-left: 3px solid #2196F3;
            writing-mode: vertical-lr;
            text-orientation: mixed;
            line-height: 1.8;
            pointer-events: none;
        `;

        function updateGuide() {
            guideBox.innerHTML = `
                <div style="color: #2196F3; font-weight: bold; margin-bottom: 10px;">zwols 视频控制指南</div>
                <div style="margin-bottom: 10px;">🖱️滚轮:快进/快退5秒</div>
                <div style="margin-bottom: 10px;">⇧+滚轮:调整播放速度</div>
                <div style="color: #2196F3;">当前: ${video.playbackRate.toFixed(2)}x</div>
            `;
        }

        updateGuide();
        document.body.appendChild(guideBox);
        video.addEventListener('ratechange', updateGuide);

        const showGuide = () => {
            updateGuide();
            guideBox.style.opacity = '1';
            guideBox.style.transform = 'translateY(-50%) translateX(0)';
        };
        const hideGuide = () => {
            guideBox.style.opacity = '0';
            guideBox.style.transform = 'translateY(-50%) translateX(-150px)';
        };

        [video, container].forEach(el => {
            el.addEventListener('mouseenter', showGuide);
            el.addEventListener('mouseleave', hideGuide);
        });

        setTimeout(hideGuide, 5000);
    }
})();