nascent / YouTube Variable Playback Speed

// ==UserScript==
// @name         YouTube Variable Playback Speed
// @namespace    https://youtube.com/
// @version      1.0
// @description  Increase/decrease YouTube video playback speed by 0.25 increments using + and - keys, even beyond the default 2× limit.
// @author       nascent
// @match        *://www.youtube.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant        none
// @run-at       document-end
// @updateURL    https://openuserjs.org/meta/nascent/YouTube_Variable_Playback_Speed.meta.js
// @downloadURL  https://openuserjs.org/install/nascent/YouTube_Variable_Playback_Speed.user.js
// @copyright    2025, nascent (https://openuserjs.org/users/nascent)
// @license      MIT
// ==/UserScript==

(function() {
    "use strict";

    // Function to display an overlay with the current playback speed
    function showPlaybackSpeed(speed) {
        let overlay = document.getElementById("playbackSpeedOverlay");
        if (!overlay) {
            overlay = document.createElement("div");
            overlay.id = "playbackSpeedOverlay";
            // Style the overlay popup
            Object.assign(overlay.style, {
                position: "fixed",
                top: "20px",
                right: "20px",
                backgroundColor: "rgba(0,0,0,0.7)",
                color: "#fff",
                padding: "10px",
                borderRadius: "5px",
                fontSize: "20px",
                zIndex: "9999",
                transition: "opacity 0.5s",
            });
            document.body.appendChild(overlay);
        }
        overlay.textContent = "Playback speed: " + speed.toFixed(2) + "×";
        overlay.style.opacity = "1";

        // Clear any previous fade-out timeout and schedule a new one
        if (overlay.hideTimeout) {
            clearTimeout(overlay.hideTimeout);
        }
        overlay.hideTimeout = setTimeout(() => {
            overlay.style.opacity = "0";
        }, 1000);
    }

    // Listen for keydown events on the document
    document.addEventListener("keydown", (e) => {
        // Avoid interfering if the user is typing in an input, textarea, or a content-editable element
        if (
            e.target.matches("input, textarea") ||
            e.target.isContentEditable
        ) {
            return;
        }

        // Get the video element
        var video = document.querySelector("video");
        if (!video) return;

        // If the "-" or "_" key is pressed, decrease the speed
        if (e.key === "-" || e.key === "_") {
            let newRate = video.playbackRate - 0.25;
            // Prevent speeds lower than 0.25x
            if (newRate < 0.25) {
                newRate = 0.25;
            }
            video.playbackRate = newRate;
            showPlaybackSpeed(newRate);
        }
        // If the "+" or "=" key is pressed, increase the speed
        else if (e.key === "+" || e.key === "=") {
            let newRate = video.playbackRate + 0.25;
            video.playbackRate = newRate;
            showPlaybackSpeed(newRate);
        }
    });
})();