Created
October 22, 2025 14:08
-
-
Save f13end/5b159799dd577171185486173f9156ad to your computer and use it in GitHub Desktop.
Automatically adjust YouTube playback speed based on video type (music vs normal)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name YouTube Auto Speed Adjuster | |
// @namespace https://github.com/f13end | |
// @version 1.0 | |
// @description Automatically adjust YouTube playback speed based on video type (music vs normal) | |
// @author F13END | |
// @homepageURL https://github.com/f13end | |
// @match https://www.youtube.com/* | |
// @grant none | |
// ==/UserScript== | |
(function () { | |
'use strict'; | |
const NORMAL_SPEED = 2.0; | |
const MUSIC_SPEED = 1.0; | |
const MUSIC_KEYWORDS = [ | |
"official music video", | |
"official video", | |
"lyrics", | |
"song", | |
"mix", | |
"audio", | |
"remix", | |
"album", | |
"Dj", | |
"single", | |
"music", | |
"track" | |
]; | |
function isMusicVideo(title, channel) { | |
const lowerTitle = (title || "").toLowerCase(); | |
const lowerChannel = (channel || "").toLowerCase(); | |
if (MUSIC_KEYWORDS.some(keyword => lowerTitle.includes(keyword))) return true; | |
if (lowerChannel.includes("music")) return true; | |
return false; | |
} | |
function setPlaybackSpeed(video, speed) { | |
if (video && Math.abs(video.playbackRate - speed) > 0.001) { | |
video.playbackRate = speed; | |
console.log(`YouTube Auto Speed (f13end): ${speed}x applied`); | |
} | |
} | |
function getTitleElement() { | |
return document.querySelector('h1.title yt-formatted-string') || document.querySelector('#container h1'); | |
} | |
function getChannelElement() { | |
return document.querySelector('#meta-contents ytd-channel-name a') || document.querySelector('#text-container yt-formatted-string'); | |
} | |
function checkAndSetSpeed() { | |
const video = document.querySelector('video'); | |
const titleEl = getTitleElement(); | |
const channelEl = getChannelElement(); | |
if (!video) return; | |
const title = titleEl ? (titleEl.textContent || "") : ""; | |
const channel = channelEl ? (channelEl.textContent || "") : ""; | |
const speed = isMusicVideo(title, channel) ? MUSIC_SPEED : NORMAL_SPEED; | |
setPlaybackSpeed(video, speed); | |
} | |
let lastUrl = location.href; | |
const urlObserver = new MutationObserver(() => { | |
const currentUrl = location.href; | |
if (currentUrl !== lastUrl) { | |
lastUrl = currentUrl; | |
setTimeout(checkAndSetSpeed, 1200); | |
setTimeout(checkAndSetSpeed, 2400); | |
setTimeout(checkAndSetSpeed, 4000); | |
} | |
}); | |
urlObserver.observe(document.body, { childList: true, subtree: true }); | |
const videoListObserver = new MutationObserver(() => checkAndSetSpeed()); | |
videoListObserver.observe(document, { childList: true, subtree: true }); | |
window.addEventListener('load', () => setTimeout(checkAndSetSpeed, 1000)); | |
window.addEventListener('yt-navigate-finish', () => setTimeout(checkAndSetSpeed, 1000)); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment