Skip to content

Instantly share code, notes, and snippets.

@haynesgt
Last active August 16, 2025 20:41
Show Gist options
  • Select an option

  • Save haynesgt/05b472c2f7d1cc026d1450bb36c7b141 to your computer and use it in GitHub Desktop.

Select an option

Save haynesgt/05b472c2f7d1cc026d1450bb36c7b141 to your computer and use it in GitHub Desktop.
YouTube video speeds TamperMonkey widget
// ==UserScript==
// @name YouTube video speeds
// @namespace http://tampermonkey.net/
// @version 2025-08-13
// @description Adds a button box to change speeds of youtube videos
// @author You
// @match https://youtube.com/*
// @match https://www.youtube.com/*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant none
// ==/UserScript==
(function() {
console.log("Adding button box")
// Create container
const panel = document.createElement('div');
panel.style.position = 'fixed';
panel.style.top = '50px';
panel.style.left = '50px';
panel.style.background = 'rgba(0,0,0,0.8)';
panel.style.padding = '5px';
panel.style.borderRadius = '5px';
panel.style.zIndex = 999999;
panel.style.display = 'flex';
panel.style.alignItems = 'center';
panel.style.gap = '5px';
panel.style.cursor = 'move';
panel.style.color = 'white';
// Speeds to add
const speeds = [0.25, 0.5, 1, 1.5, 2, 3, 4, 8];
// Checkbox for pitch
const pitchLabel = document.createElement('label');
pitchLabel.style.color = 'white';
pitchLabel.style.fontSize = '12px';
const pitchCheckbox = document.createElement('input');
pitchCheckbox.type = 'checkbox';
pitchCheckbox.checked = true; // default keep pitch normal
pitchLabel.appendChild(pitchCheckbox);
// Update pitch setting for all videos
function updatePitch() {
document.querySelectorAll('video').forEach(v => {
v.preservesPitch = pitchCheckbox.checked;
v.mozPreservesPitch = pitchCheckbox.checked;
v.webkitPreservesPitch = pitchCheckbox.checked;
});
}
pitchCheckbox.addEventListener('change', updatePitch);
// Create buttons
speeds.forEach(s => {
const btn = document.createElement('button');
btn.textContent = s + 'x';
btn.style.padding = '5px 8px';
btn.style.fontSize = '14px';
btn.style.cursor = 'pointer';
btn.onclick = () => {
document.querySelectorAll('video').forEach(v => {
v.playbackRate = s;
updatePitch();
});
};
panel.appendChild(btn);
});
// Add checkbox after buttons
panel.appendChild(pitchLabel);
panel.appendChild(document.createTextNode(' Keep Pitch'));
// Make draggable
let isDragging = false, offsetX = 0, offsetY = 0;
panel.addEventListener('mousedown', e => {
isDragging = true;
offsetX = e.clientX - panel.offsetLeft;
offsetY = e.clientY - panel.offsetTop;
});
document.addEventListener('mousemove', e => {
if (isDragging) {
panel.style.left = (e.clientX - offsetX) + 'px';
panel.style.top = (e.clientY - offsetY) + 'px';
}
});
document.addEventListener('mouseup', () => {isDragging = false});
document.body.appendChild(panel);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment