Greasy Fork

Greasy Fork is available in English.

bilibili视频倍速

在B站的倍速选择中添加拖动条设置倍速

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         bilibili视频倍速
// @namespace    http://tampermonkey.net/
// @version      2025-10-31
// @description  在B站的倍速选择中添加拖动条设置倍速
// @author       Peng
// @match        *://bilibili.tv/*
// @match        *://www.bilibili.com/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// ==/UserScript==
const sliderHTML = `
    <div class="bpx-player-speed-slider" style="padding: 8px 12px;">
        <div class="bpx-player-speed-slider-header">
            <div class="bpx-player-speed-selected">custom speed</div>
        </div>
        <div class="bpx-player-speed-slider-container">
            <div class="bpx-player-speed-indicator">
                <li class="bpx-player-speed-text bpx-player-ctrl-playbackrate-menu-item" data-value="1.00">1.00x</li>
            </div>
            <input id="bpx-player-speed-slider"
                   type="range"
                   min="0.25"
                   max="4"
                   step="0.05"
                   value="1.0"
                   style="width: 100%; margin: 8px 0;">
        </div>
    </div>
    `; // 拖动条html ai写的,感觉比较蠢,不过html只要能用就行,就懒得改了
function changeSpeed()
{
    // const text=[1.75,2,2.25,2.5,2.75,3,3.25,3.5,3.75,4].reverse();
    // text=text.map(sp=>`<li class="bpx-player-ctrl-playbackrate-menu-item" data-value="${sp}">${sp}x</li>`).join("");
    const a = document.querySelector(".bpx-player-ctrl-playbackrate-menu"); // ul 菜单
    if (!a) return;
    // document.querySelectorAll(".bpx-player-ctrl-playbackrate-menu-item")[0].remove(); //移除2倍速
    a.style.width='130px';
    a.insertAdjacentHTML('afterbegin',sliderHTML);
    const slider = document.getElementById('bpx-player-speed-slider'); // 拖动条 input
    const speedText = document.querySelector(".bpx-player-speed-text"); // li
    // const speedValue = document.querySelector(".bpx-player-speed-value"); // 文本显示 div
    // const result=document.querySelector(".bpx-player-ctrl-playbackrate-result");
    slider.addEventListener("input", function() { // 用户拖动时
        if (speedText.isContentEditable) {
            return;
        }
        const value = parseFloat(this.value).toFixed(2);
        console.log(slider.value);
        speedText.textContent = `${value}x`;
        // speedValue.textContent = value;
        speedText.dataset.value = value;
    });
    slider.addEventListener("change", function() { // 用户拖动结束后
        speedText.click();
    });
    // 点击li标签
    speedText.addEventListener("click", function(e) {
        // e.isTrusted 检查是否为真实用户点击
        // 如果是用户点击,并且当前不是编辑状态,则可以进行响应
        // 如果是脚本点击 (isTrusted: false) 或 正在编辑中,则不处理
        if (e.isTrusted && !this.isContentEditable) {
            e.preventDefault();
            e.stopPropagation();// 阻止事件冒泡

            this.contentEditable = true;
            this.textContent = this.dataset.value; // 将 "1.00x" 变为 "1.00"
            this.style.backgroundColor = "#eee";
            this.style.color = "#222";
            this.style.outline = "1px solid #00a1d6";

            // 自动全选文本
            const range = document.createRange();
            range.selectNodeContents(this);
            const sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        }
    });

    // 按下回车
    speedText.addEventListener("keydown", function(e) {
        if (e.key === "Enter") {
            e.preventDefault();
            this.blur(); // 触发失焦
        }
    });

    // 3. 失焦 (输入完成)
    speedText.addEventListener("blur", function() {
        this.contentEditable = false;
        this.style.backgroundColor = ""; // 恢复样式
        this.style.color = "";
        this.style.outline = "";

        // 获取、校验、格式化值
        let value = parseFloat(this.textContent);
        if (isNaN(value)) value = 1.0;
        if (value < 0.25) value = 0.25;
        if (value > 4) value = 4.0;
        const formattedValue = value.toFixed(2);

        // 将格式化后的值同步回所有组件
        this.textContent = `${formattedValue}x`;
        this.dataset.value = formattedValue;
        slider.value = formattedValue;

        // 触发一次非受信任(isTrusted: false)的点击从而应用速度并关闭菜单
        this.click();
    });
}
(function() {
    'use strict';
    const timeout = 5000; // 5秒超时
    const startTime = Date.now();
    console.log('start change video')
    var interval = setInterval(function() {
    var confirmButton = document.querySelector('.bpx-player-ctrl-playbackrate-menu');
    console.log(confirmButton)
    if (confirmButton) {
        console.log('find out');
        changeSpeed();
        clearInterval(interval); // 取消定时器
    } else if (Date.now() - startTime > timeout) {
        console.log('cant find out');
        clearInterval(interval);
    }
}, 500);
})();