Greasy Fork

来自缓存

Greasy Fork is available in English.

OneKey Speed Control

A script to control video playback speed and navigation keys

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         OneKey Speed Control
// @namespace    http://tampermonkey.net/
// @version      2024-03-03
// @description  A script to control video playback speed and navigation keys
// @author       ExistoT01
// @match        https://*/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    const logPrefix = "[OKSC]: " //日志前缀

    const TIME_UNIT = 10; //快进,倒带单位(s)
    const RATE_UNIT = 0.25; //调整倍率单位
    const RATE_MAX = 10; //最大播放速率
    const RATE_MIN = 0.25; //最小播放速率
    const LOCKED_SPEED = 3; //倍速播放速度

    const TYPE_CHANGE_SPEED = 1; //类型1,改变视频播放速度
    const TYPE_LOCK_SPEED = 2; //类型2,锁定倍速播放
    const TYPE_CHANGE_PROGRESS_FORWORD = 3; //类型3,快进
    const TYPE_CHANGE_PROGRESS_REWIND = 4; //类型4,倒退
    const TYPE_PLAY = 5;
    const TYPE_PAUSE = 6;

    const KEY_INC_SPEED = 'x';
    const KEY_DEC_SPEED = 'z';
    const KEY_LOCK_SPEED = 'u';
    const KEY_REWIND = 'j';
    const KEY_FORWORD = 'l';
    const KEY_PLAY_OR_PAUSE = 'k';

    const MSG_VIDEO_NOT_FOUND = 'video element not found!';

    const HOSTNAME_YOUTUBE = 'www.youtube.com';
    const HOSTNAME_DISNEYPLUS = 'www.disneyplus.com';

    const VIDEO_SELECTOR = 'video';
    const VIDEO_SELECTOR_DISNEYPLUS = '#hivePlayer';

    let originalSpeed;
    let isSpeedLocked = false;
    let timeoutId;

    // Your code here...
    document.addEventListener('keydown', function(event) {
        // console.log(logPrefix, 'keydown', event.key);

        if (isSpeedLocked) {
            return;
        }

        let video = getVideo();
        if (!video) return;

        // Increase speed
        if (event.key === KEY_INC_SPEED) {
            video.playbackRate = Math.min(video.playbackRate + RATE_UNIT, RATE_MAX);
            showNotification(TYPE_CHANGE_SPEED, video.playbackRate);
            return;
        }
        // Decrease speed
        else if (event.key === KEY_DEC_SPEED) {
            video.playbackRate = Math.max(video.playbackRate - RATE_UNIT, RATE_MIN);
            showNotification(TYPE_CHANGE_SPEED, video.playbackRate);
            return;
        }
        // Lock speed
        else if (event.key === KEY_LOCK_SPEED) {
            isSpeedLocked = true;
            originalSpeed = video.playbackRate;
            video.playbackRate = LOCKED_SPEED;
            clearTimeout(timeoutId);
            showNotification(TYPE_LOCK_SPEED, LOCKED_SPEED);
            return;
        }

        // Youtube already has this feature
        if (window.location.hostname !== HOSTNAME_YOUTUBE) {
            switch (event.key) {
                case KEY_REWIND: // Jump back 10 seconds
                    video.currentTime = Math.max(video.currentTime - TIME_UNIT, 0);
                    showNotification(TYPE_CHANGE_PROGRESS_REWIND);
                    break;
                case KEY_PLAY_OR_PAUSE: // Toggle play/pause
                    if (video.paused) {
                        video.play();
                        showNotification(TYPE_PLAY, 0);
                    } else {
                        video.pause();
                        showNotification(TYPE_PAUSE, 0);
                    }
                    break;
                case KEY_FORWORD: // Jump forward 10 seconds
                    video.currentTime = Math.min(video.currentTime + TIME_UNIT, video.duration);
                    showNotification(TYPE_CHANGE_PROGRESS_FORWORD);
                    break;
            }
        }
    });

    document.addEventListener('keyup', function(event) {
        // console.log(logPrefix, 'keyup', event.key);

        isSpeedLocked = false;

        let video = getVideo();
        if (!video) return;

        if (event.key === KEY_LOCK_SPEED) {
            video.playbackRate = originalSpeed;
            notification.style.display = 'none';
            showNotification(TYPE_CHANGE_SPEED, originalSpeed);
        }
    })


    // CSS for the notification
    var style = document.createElement('style');
    style.type = 'text/css';

    // Use a text node to safely insert CSS rules
    style.appendChild(document.createTextNode(`.speed-notification {
        position: fixed;
        bottom: 50px;
        right: 20px;
        background-color: black;
        color: white;
        padding: 8px;
        border-radius: 4px;
        z-index: 9999999;
        display: none;
    }`));

    document.head.appendChild(style);

    // Create the notification element
    var notification = document.createElement('div');
    notification.className = 'speed-notification';
    document.body.appendChild(notification);

    // Function to show notification
    function showNotification(type, speed) {

        if (type === TYPE_LOCK_SPEED) {
            notification.textContent = 'Speed: ' + LOCKED_SPEED + 'x';
            notification.style.display = 'block';
            return;
        }

        if (type === TYPE_CHANGE_SPEED) {
            notification.textContent = 'Speed: ' + speed + 'x';
        } else if (type === TYPE_CHANGE_PROGRESS_FORWORD) {
            notification.textContent = '-->>';
        } else if (type === TYPE_CHANGE_PROGRESS_REWIND) {
            notification.textContent = '<<--';
        } else if (type === TYPE_PLAY) {
            notification.textContent = '  ||  ';
        } else if (type === TYPE_PAUSE) {
            notification.textContent = ' |> ';
        }

        notification.style.display = 'block';

        // Hide the notification after 2 seconds
        clearTimeout(timeoutId);
        timeoutId = setTimeout(function() {
            notification.style.display = 'none';
        }, 2000);

    }

    // function to get video element
    function getVideo() {
        let video;

        // Disney+ odd version
        // if (window.location.hostname === HOSTNAME_DISNEYPLUS) {
        //     let player = document.querySelector('disney-web-player');
        //     if (!player) return;
        //     video = player.shadowRoot.querySelector('video');
        // }
        // else {
        //     video = document.querySelector('video');
        // }

        if (window.location.hostname === HOSTNAME_DISNEYPLUS) {
            video = document.querySelector(VIDEO_SELECTOR_DISNEYPLUS);
        }
        else {
            video = document.querySelector(VIDEO_SELECTOR);
        }


        if (!video) {
            console.log(logPrefix, MSG_VIDEO_NOT_FOUND);
            return;
        }

        return video;
    }






})();