B站视频长按加速

实现类YouTube的在播放窗口长按鼠标左键对视频进行加速

// ==UserScript==
// @name         B站视频长按加速
// @version      1.0.4
// @description  实现类YouTube的在播放窗口长按鼠标左键对视频进行加速
// @author       Marx Engels
// @license      ISC
// @icon         https://i0.hdslb.com/bfs/static/jinkela/long/images/512.png
// @match        https://www.bilibili.com/*
// @require      https://greasyfork.org/scripts/38220-mscststs-tools/code/MSCSTSTS-TOOLS.js?version=1026406
// @require      https://greasyfork.org/scripts/374462-%E9%BC%A0%E6%A0%87%E9%95%BF%E6%8C%89-longpress/code/%E9%BC%A0%E9%95%BF%E6%8C%89-LongPress.js?version=645860
// @namespace https://greasyfork.org/users/1310364
// ==/UserScript==

(async function() {
    'use strict';

    // 自定义倍速界面
    function createSpeedControlUI() {
        const container = document.createElement('div');
        container.style.position = 'fixed';
        container.style.zIndex = '9999';
        container.style.backgroundColor = 'rgba(255, 255, 255, 0.9)';
        container.style.padding = '10px';
        container.style.borderRadius = '5px';
        container.style.color = '#00a1d6';
        container.style.bottom = '10px';
        container.style.right = '10px';

        const label = document.createElement('label');
        label.textContent = '左键长按时倍速: ';
        label.style.marginRight = '5px';

        const select = document.createElement('select');
        const speeds = [1.1, 1.2, 1.5, 2, 2.5, 3, 3.5, 4];
        speeds.forEach(speed => {
            const option = document.createElement('option');
            option.value = speed;
            option.textContent = speed + 'x';
            select.appendChild(option);
        });

        const button = document.createElement('button');
        button.textContent = '设置';
        button.style.marginLeft = '5px';

        container.appendChild(label);
        container.appendChild(select);
        container.appendChild(button);
        document.body.appendChild(container);

        return { select, button };
    }

    // 获取存储的倍速
    function getStoredSpeed() {
        return parseFloat(localStorage.getItem('customSpeed')) || 1;
    }

    // 设置存储的倍速
    function setStoredSpeed(speed) {
        localStorage.setItem('customSpeed', speed);
    }

    try {
        const video = await mscststs.wait("#bilibili-player video");
        if (!video) throw new Error("未找到视频播放元素");

        const { select, button } = createSpeedControlUI();
        select.value = getStoredSpeed();

        let customSpeed = parseFloat(select.value);

        button.addEventListener('click', () => {
            const speed = parseFloat(select.value);
            if (!isNaN(speed)) {
                setStoredSpeed(speed);
                customSpeed = speed;
                alert(`左键长按时倍速已设置为: ${customSpeed}x`);
            } else {
                alert("请选择有效的倍速!");
            }
        });

        const playerContainer = document.querySelector("#bilibili-player");

        // 在长按时禁用鼠标事件
        onLongPress(video, () => {
            const player = window.player;
            const prevPlayBackRate = player?.getPlaybackRate();
            if (typeof prevPlayBackRate !== "number") throw new Error("无法获取播放速率");

            player.setPlaybackRate(customSpeed);

            const toastId = player.toast.create({ text: `${customSpeed}x 加速中 >>`, duration: Infinity });

            playerContainer.style.pointerEvents = "none";  // 禁用鼠标事件

            const mouseUpHandler = () => {
                player.toast.remove(toastId);
                player.setPlaybackRate(prevPlayBackRate);
                playerContainer.style.pointerEvents = "auto";  // 重新启用鼠标事件

                // 手动触发一个点击事件,确保鼠标事件立即生效
                const clickEvent = new MouseEvent('click', { bubbles: true, cancelable: true });
                video.dispatchEvent(clickEvent);

                document.removeEventListener("mouseup", mouseUpHandler);
            };

            document.addEventListener("mouseup", mouseUpHandler, { once: true });
        }, 500);

    } catch (error) {
        console.error("脚本出现错误:", error);
    }
})();