Greasy Fork is available in English.

b站多倍速调节(支持视频)已支持自动变速

b站多倍速调节(支持视频)已支持自动变速🤞🤞🤞~~~

// ==UserScript==
// @name         b站多倍速调节(支持视频)已支持自动变速
// @namespace    lgldlk
// @version      1.1
// @description  b站多倍速调节(支持视频)已支持自动变速🤞🤞🤞~~~
// @author       lgldlk
// @include      *://*.bilibili.com/video/*
// @include      *://*.bilibili.tv/video/*
// @include      *://*.bilibili.com/bangumi/*
// @include      *://*.bilibili.tv/bangumi/*
// @run-at       document-start
// @grant        none
// @license MIT
// ==/UserScript==
let cacheRate = 1,
  cacheFlag = true,
  rateArr = [5, 4.5, 4, 3.5, 3, 2.5, 2, 1.5, 1, 0.5, 0.1];

let selector = document.querySelector.bind(document);

function waitForNode(nodeSelector, callback) {
  if (nodeSelector()) {
    callback();
  } else {
    setTimeout(() => {
      waitForNode(nodeSelector, callback);
    }, 300);
  }
}
function debounce(func, wait) {
  let timer;
  return function () {
    let args = arguments;
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, args);
    }, wait);
  };
}
function deleteChild(element) {
  while (element.firstChild) {
    element.removeChild(element.firstChild);
  }
}

const key = 'lgldl_rate_key';

function setRate(video, rate) {
  video.playbackRate = rate;
  cacheRate = rate;
  localStorage.setItem(key, rate);
  setRateText(rate);
}

function setRateText(rate) {
  const rateElement = selector('.bpx-player-ctrl-playbackrate-result');
  if (rateElement) {
    rateElement.innerText = `${rate}x`;
  }
}

const initRateBody = function (callBack) {
  waitForNode(
    () => selector('ul.bpx-player-ctrl-playbackrate-menu'),
    () => {
      const menuNode = selector('ul.bpx-player-ctrl-playbackrate-menu');
      cacheRate = Number(localStorage.getItem(key) || 1);
      const videoElement = selector('video') || selector('bwp-video');
      if (!videoElement) {
        alert('清空缓存后刷新即可使用');
        return;
      }

      deleteChild(menuNode);
      rateArr.forEach((rate) => {
        const rateItem = document.createElement('li');
        rateItem.classList.add('bpx-player-ctrl-playbackrate-menu-item');
        rateItem.innerText = `${rate}x`;
        rateItem.style.height = '30px';
        rateItem.style.fontSize = '16px';
        rateItem.style.lineHeight = '30px';
        rateItem.addEventListener('click', () => {
          setRate(videoElement, rate);
        });
        menuNode.appendChild(rateItem);
      });

      const applyCachedRate = () => {
        if (cacheRate !== videoElement.playbackRate) {
          setRate(videoElement, cacheRate);
        }
      };
      applyCachedRate();
      videoElement.addEventListener('playing', applyCachedRate);
      callBack && callBack();
    }
  );
};
window.addEventListener('load', () => initRateBody(null));
window.onhashchange = () => initRateBody();