// ==UserScript==
// @name YouTube Playback Speed Buttons
// @name:zh-CN YouTube 播放速度按钮
// @name:zh-HK YouTube 播放速度按鈕
// @description Adds playback speed buttons to youtube player control bar.
// @description:zh-CN 在 YouTube 播放器控制栏中添加播放速度按钮。
// @description:zh-HK 在 YouTube 播放器控制列中加入播放速度按鈕。
// @version 1.1.2
// @license MIT
// @author bowencool
// @match https://www.youtube.com/*
// @namespace https://www.youtube.com/
// @author bowencool
// @license MIT
// @homepageURL https://greasyfork.org/scripts/475864
// @supportURL https://github.com/bowencool/Tampermonkey-Scripts/issues
// @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @run-at document-end
// @require https://cdn.jsdelivr.net/gh/bowencool/Tampermonkey-Scripts@f59cc91442dd34eb28e0d270486da5c7ac8d2d50/shared/waitForElementToExist.js
// @grant GM_addStyle
// ==/UserScript==
"use strict";
const language = navigator.language.toLowerCase();
const isTraditionalChinese = language.startsWith("zh-hant") || /^zh-(tw|hk|mo)/.test(language);
const labels = isTraditionalChinese
? {
faster: "加快 10%",
reset: "重設為 1 倍速",
slower: "減慢 10%"
}
: language.startsWith("zh")
? {
faster: "加快 10%",
reset: "恢复为 1 倍速",
slower: "减慢 10%"
}
: {
faster: "10% faster",
reset: "Reset to 1x",
slower: "10% slower"
};
async function main() {
const menuR = await waitForElementToExist(".ytp-right-controls-left");
const video = await waitForElementToExist(".html5-main-video");
if (window.trustedTypes && window.trustedTypes.createPolicy) {
window.trustedTypes.createPolicy("default", {
createHTML: (string, sink) => string,
});
}
GM_addStyle(`.speed-button svg {
padding: 0!important;
}`);
const storedPlaybackRate = parseFloat(
sessionStorage.getItem("playback-rate"),
10
);
if (storedPlaybackRate > 0) {
video.playbackRate = storedPlaybackRate;
}
const fasterButton = document.createElement("button");
fasterButton.setAttribute("aria-label", labels.faster);
fasterButton.title = labels.faster;
fasterButton.innerHTML = window.trustedTypes.defaultPolicy
.createHTML``;
fasterButton.classList.add("ytp-button", "speed-button");
fasterButton.onclick = () => {
const speed = Math.ceil(video.playbackRate * 11) / 10;
console.log(speed);
video.playbackRate = speed;
sessionStorage.setItem("playback-rate", speed);
};
menuR.prepend(fasterButton);
const resetButton = document.createElement("button");
resetButton.setAttribute("aria-label", labels.reset);
resetButton.title = labels.reset;
resetButton.innerHTML = window.trustedTypes.defaultPolicy
.createHTML``;
resetButton.classList.add("ytp-button", "speed-button");
resetButton.onclick = () => {
video.playbackRate = 1;
sessionStorage.removeItem("playback-rate");
};
menuR.prepend(resetButton);
const slowerButton = document.createElement("button");
slowerButton.setAttribute("aria-label", labels.slower);
slowerButton.title = labels.slower;
slowerButton.innerHTML = window.trustedTypes.defaultPolicy
.createHTML``;
slowerButton.classList.add("ytp-button", "speed-button");
slowerButton.onclick = () => {
const speed = Math.floor(video.playbackRate * 9) / 10;
console.log(speed);
if (speed === 0) return;
video.playbackRate = speed;
sessionStorage.setItem("playback-rate", speed);
};
menuR.prepend(slowerButton);
}
main();