Greasy Fork

来自缓存

Greasy Fork is available in English.

视频倍速工具

除youtube以外按c加速,按x减速,按z复位,youtube按v加速。点击右上角油猴按钮可开关视频速度记忆功能。

// ==UserScript==
// @name         视频倍速工具
// @namespace    http://tampermonkey.net/
// @version      0.3.12
// @description  除youtube以外按c加速,按x减速,按z复位,youtube按v加速。点击右上角油猴按钮可开关视频速度记忆功能。
// @author       call duck
// @match        *://*/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bilibili.com
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addValueChangeListener
// @run-at document-end
// @license MIT
// ==/UserScript==

// 使用方法:除youtube以外按c加速,按x减速,按z复位,youtube按v加速。


var aab = 111;

(function () {
    "use strict";

    if (window.innerWidth < 100) {
        return;
    }



    const REMEMBER_KEY = `${location.hostname}_da4e1a5f0c5b46cdadadf70af3c19f37`;
    let isRememberSpeed = GM_getValue(REMEMBER_KEY, false);

    const SPEED_KEY = "2779054e81654c2990dd9d2bfe9202aa";
    const originSpeed = localStorage.getItem(SPEED_KEY);
    let speed;
    if (!originSpeed) {
        speed = 1;
        localStorage.setItem(SPEED_KEY, '1');
    } else if (isRememberSpeed) {
        speed = parseFloat(originSpeed);
    } else {
        speed = 1;
    }
    speed = parseFloat(speed.toFixed(2));
    let videos = getVideos()
    const step = 0.05;

    let rememberMenuId;




    function addMenus() {
        if (!isRememberSpeed) {
            addOpenRememberMenu();
        } else {
            addCloseRememberMenu();
        }

        GM_addValueChangeListener(
            REMEMBER_KEY,
            function name(key, oldValue, newValue) {
                GM_unregisterMenuCommand(rememberMenuId);
                if (newValue === true) {
                    addCloseRememberMenu();
                } else {
                    addOpenRememberMenu();
                }
            }
        );
    }
    addMenus();

    const blackSites = GM_getValue("blackSites", "").split(',')
    const site = window.location.hostname
    let blackSiteMenuId

    async function addBlackSiteMenu() {
        if (blackSiteMenuId) GM_unregisterMenuCommand(blackSiteMenuId);
        blackSiteMenuId = await GM.registerMenuCommand("添加当前网站到黑名单", async () => {
            if (blackSites.indexOf(site) === -1) {
                blackSites.push(site)
                GM_setValue("blackSites", blackSites.join(','))
                notify("当前网站已添加到黑名单");
                addRemoveBlackSiteMenu()
            }
        });
    }

    async function addRemoveBlackSiteMenu() {
        if (blackSiteMenuId) GM_unregisterMenuCommand(blackSiteMenuId);
        blackSiteMenuId = await GM.registerMenuCommand("当前网站从黑名单中移除", async () => {
            if (blackSites.indexOf(site) !== -1) {
                blackSites.splice(blackSites.indexOf(site), 1)
                GM_setValue("blackSites", blackSites.join(','))
                notify("当前网站已从黑名单中移除");
                addBlackSiteMenu()

            }
        });
    }

    if (blackSites.indexOf(site) !== -1) {
        addRemoveBlackSiteMenu()
        return
    } else {
        addBlackSiteMenu()
    }

    async function addOpenRememberMenu() {
        if (rememberMenuId) GM_unregisterMenuCommand(rememberMenuId);
        rememberMenuId = await GM.registerMenuCommand("打开视频速度记忆功能", async () => {
            GM_setValue(REMEMBER_KEY, true);
            videos.forEach((v) => {
                notify("视频播放速度记忆功能已打开", v);
            });
        });
    }

    async function addCloseRememberMenu() {
        if (rememberMenuId) GM_unregisterMenuCommand(rememberMenuId);
        rememberMenuId = await GM.registerMenuCommand("关闭视频速度记忆功能", async () => {
            GM_setValue(REMEMBER_KEY, false);

            videos.forEach((v) => {
                notify("视频播放速度记忆功能已关闭", v);
            });
        });
    }


    function getVideos() {
        let videoElements = Array.prototype.slice.call(
            document.getElementsByTagName("video")
        );
        const audioElements = Array.prototype.slice.call(
            document.getElementsByTagName('audio')
        )
        videoElements = videoElements.concat(audioElements)

        if (window.location.hostname === "www.bilibili.com") {
            const bPlayerCollection = document.getElementsByTagName("bwp-video");
            if (bPlayerCollection.length > 0) {
                videoElements.push(bPlayerCollection[0]);
            }
        }

        if (
            location.hostname === "www.reddit.com" &&
            window.location.pathname.match(/\/r\/\S+\/comments\/.+/)
        ) {
            const player = document.getElementsByTagName("shreddit-player");
            if (player.length > 0) {
                const v = player[0].shadowRoot.querySelector("video");
                videoElements.push(v);
            }
        }

        /*     if (location.hostname === "www.youtube.com") {
          if (v && v.className.indexOf("video-stream") === -1) {
            notify('视频正在初始化,请稍候')
            return null
          }
        } */
        console.log(videoElements)
        return videoElements;
    }

    new Promise((res) => {
        if (videos.length === 0) {
            let count = 0;
            const maxCount = 3;
            function _getVideo() {
                setTimeout(() => {
                    videos = getVideos();
                    count++;
                    if (videos.length === 0 && count < maxCount) {
                        _getVideo();
                    } else {
                        res(videos);
                    }
                }, 1000);
            }
            _getVideo();
        } else {
            res(videos);
        }
    }).then((v) => {
        videos = v;
        syncSpeedToVideo();
    });



    function formatSpeed(s) {
        s = parseFloat(s.toFixed(2));
        if (s > 10) {
            return 10;
        }
        if (s <= 0.1) {
            return 0.1;
        }
        return s;
    }

    window.addEventListener("keypress", function (e) {
        console.log(e.key.toLowerCase());
        const activeElement = this.document.activeElement;
        if (!activeElement) {
            return
        }
        if (
            activeElement.tagName.toLowerCase() === "input" ||
            activeElement.contentEditable === 'true' ||
            activeElement.tagName.toLowerCase() === "textarea"
        ) {
            return;
        }
        const keyList = ["z", "x", "c", "e", "q", "w"];
        const key = e.key.toLowerCase();
        if (keyList.indexOf(key) === -1) {
            return;
        }
        // 获取video元素
        videos = getVideos();
        if (videos.length === 0) {
            return;
        }
        // **



        if (this.location.hostname === "www.youtube.com") {
            if (e.key.toLowerCase() === "e") {
                speed = speed + step;
                changeSpeed(videos, formatSpeed(speed));
            }

            if (e.key.toLowerCase() === "w") {
                speed = speed - step;
                changeSpeed(videos, formatSpeed(speed));
            }
            if (e.key.toLowerCase() === "q") {
                speed = 1;
                changeSpeed(videos, formatSpeed(speed));
            }
        } else {
            if (e.key.toLowerCase() === "c") {
                speed = speed + step;
                changeSpeed(videos, formatSpeed(speed));
            }

            if (e.key.toLowerCase() === "x") {
                speed = speed - step;
                changeSpeed(videos, formatSpeed(speed));
            }
            if (e.key.toLowerCase() === "z") {
                speed = 1;
                changeSpeed(videos, formatSpeed(speed));
            }
        }

        // youtube单独处理。
        // if (
        //     this.location.hostname === "www.youtube.com" &&
        //     e.key.toLowerCase() === "e"
        // ) {
        //     speed = speed + step;
        //     changeSpeed(videos, formatSpeed(speed));
        // }

    });


    function changeSpeed(videos, speed) {
        console.log(videos, speed);
        videos.forEach((video) => {
            video.playbackRate = speed;
            localStorage.setItem(SPEED_KEY, speed.toString());

            video.removeEventListener("playing", syncSpeedToVideo);
            video.removeEventListener("play", syncSpeedToVideo);

            video.addEventListener("playing", syncSpeedToVideo);
            video.addEventListener("play", syncSpeedToVideo);

            notify(video.playbackRate.toString(), video);
        });
    }

    function syncSpeedToVideo() {
        videos.forEach((video) => {
            setTimeout(() => {
                video.playbackRate = formatSpeed(speed);
            }, 1);
        });
    }


    function notify(msg, video) {
        console.log('notify')
        if (video && video.offsetWidth < 200) {
            return
        }
        const className = "edbe85b469d47a8833b84e259864e33";
        const box = document.createElement("div");
        box.className = className;
        box.style.background = "#333";
        box.style.color = "#fff";
        box.style.padding = "8px 20px";
        box.style.position = "fixed";
        box.style.margin = "auto";
        box.style.left = "50%";
        box.style.top = "60px";
        box.style.transform = "translateX(-50%)";
        box.style.borderRadius = "5px";
        box.style.zIndex = "10000";
        box.style.fontSize = "16px";
        box.innerText = msg;
        // const oldBox = document.querySelectorAll("." + className);
        const oldBox = Array.from(document.getElementsByClassName(className));
        if (oldBox.length) {
            oldBox.forEach((b) => {
                b.remove();
            });
        }

        if (video && document.fullscreenElement) {
            video.parentElement.appendChild(box);
        } else {
            document.body.appendChild(box);
        }
        setTimeout(() => {
            box.remove();
        }, 2000);
    }
})();