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

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

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

(function() {
    'use strict';

    const styles = {
        base: `
            position: fixed;
            color: white;
            z-index: 2147483647;
            transition: all 0.3s ease;
        `,
        tip: `
            left: 50%;
            top: 20px;
            transform: translateX(-50%);
            background: rgba(33, 150, 243, 0.9);
            padding: 10px 20px;
            border-radius: 4px;
            font-size: 14px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
            opacity: 0;
            text-align: center;
        `,
        guide: `
            position: absolute;
            left: 20px;
            top: 50%;
            transform: translateY(-50%);
            background: rgba(0, 0, 0, 0.8);
            padding: 15px 20px;
            border-radius: 8px;
            font-size: 14px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
            opacity: 0;
            border-left: 3px solid #2196F3;
            line-height: 1.8;
            pointer-events: none;
            text-align: left;
        `,
        speedIndicator: `
            position: absolute;
            top: 60px;
            right: 20px;
            background: rgba(0, 0, 0, 0.7);
            padding: 5px 10px;
            border-radius: 4px;
            font-size: 14px;
            pointer-events: none;
            opacity: 0;
        `
    };

    const checkVideo = setInterval(() => {
        const hostname = window.location.hostname;
        const isMissav = hostname.includes('missav.com');
        const isJable = hostname.includes('jable.tv');
        
        const video = isMissav
            ? document.querySelector('.plyr--video video')
            : isJable
                ? document.querySelector('#player-container video, #player_3 video, .plyr--video video')
                : document.querySelector('.html5-main-video, video, .youku-player video');

        if (video?.readyState >= 2) {
            clearInterval(checkVideo);
            initVideoControl(video);
        }
    }, 1000);

    function initVideoControl(video) {
        if (video.dataset.controlInitialized) return;
        video.dataset.controlInitialized = 'true';

        const hostname = window.location.hostname;
        const isYouku = hostname.includes('youku.com');
        const isMissav = hostname.includes('missav.com');
        const isJable = hostname.includes('jable.tv');
        
        const container = isMissav || isJable
            ? video.closest('.plyr--video') || video.closest('#player-container') || video.parentElement
            : isYouku 
                ? document.querySelector('.youku-player')
                : video.closest('#movie_player') || video.parentElement;

        if (!container) return;

        const wheelHandler = e => {
            e.preventDefault();
            e.stopPropagation();
            
            if (e.shiftKey) {
                video.playbackRate = Math.min(4, Math.max(0.25,
                    video.playbackRate + (e.deltaY < 0 ? 0.25 : -0.25)
                ));
                showSpeedIndicator(video, container);
            } else {
                video.currentTime = Math.min(video.duration, Math.max(0,
                    video.currentTime + (e.deltaY < 0 ? -5 : 5)
                ));
            }
            return false;
        };

        const elements = (isMissav || isJable) ? [container, video] : [isYouku ? container : video];
        elements.forEach(el => {
            el.removeEventListener('wheel', wheelHandler, { passive: false, capture: true });
            el.addEventListener('wheel', wheelHandler, { 
                passive: false,
                capture: true
            });
        });

        addGuideBox(video);
        showInitialTip();
    }

    function createElement(className, style) {
        const element = document.createElement('div');
        element.className = className;
        element.style.cssText = styles.base + style;
        return element;
    }

    function showSpeedIndicator(video, container) {
        let indicator = container.querySelector('.speed-indicator');
        if (!indicator) {
            indicator = createElement('speed-indicator', styles.speedIndicator);
            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) {
        const container = video.closest('.plyr--video') || video.parentElement;
        const guideBox = createElement('video-control-guide', styles.guide);
        
        const updateGuide = () => {
            guideBox.innerHTML = `
                <div style="margin-bottom: 5px;">按住 Alt:显示此提示</div>
                <div style="margin-bottom: 5px;">🖱️滚轮:快进/快退5秒</div>
                <div style="margin-bottom: 5px;">⇧+滚轮:调整播放速度</div>
                <div style="color: #2196F3;">当前: ${video.playbackRate.toFixed(2)}x</div>
            `;
        };

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

        document.addEventListener('keydown', e => {
            if (e.key === 'Alt') {
                e.preventDefault();
                guideBox.style.opacity = '1';
                guideBox.style.transform = 'translateY(-50%)';
            }
        });

        document.addEventListener('keyup', e => {
            if (e.key === 'Alt') {
                guideBox.style.opacity = '0';
                guideBox.style.transform = 'translateY(-50%) translateX(-20px)';
            }
        });
    }

    function showInitialTip() {
        const tip = createElement('initial-tip', styles.tip);
        tip.innerHTML = '按住 Alt 键显示视频操作指引';
        document.body.appendChild(tip);

        setTimeout(() => tip.style.opacity = '1', 100);
        setTimeout(() => {
            tip.style.opacity = '0';
            setTimeout(() => tip.remove(), 500);
        }, 5000);
    }
})();

QingJ © 2025

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