Last active
November 16, 2023 11:45
-
-
Save neon-dev/f641eb74a91a01d0e4c7434ffe0fb5ef to your computer and use it in GitHub Desktop.
Userscript that remembers and applies video playback speeds on YouTube per channel
This file contains 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 Channel Playback Speed | |
// @namespace https://gist.github.com/neon-dev | |
// @version 0.1 | |
// @description Remembers playback speeds by channel. Change the speed on one video and it automatically applies to all videos of the same channel. | |
// @author Neon | |
// @match https://www.youtube.com/* | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com | |
// @updateURL https://gist.github.com/neon-dev/f641eb74a91a01d0e4c7434ffe0fb5ef/raw | |
// @downloadURL https://gist.github.com/neon-dev/f641eb74a91a01d0e4c7434ffe0fb5ef/raw | |
// @grant GM.info | |
// @grant GM.setValue | |
// @grant GM.getValue | |
// @grant GM.deleteValue | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
let video, navigated; | |
document.addEventListener('yt-navigate-finish', (event) => { | |
navigated = true; | |
video?.removeEventListener('ratechange', speedChangeListener); | |
}); | |
document.body.addEventListener('yt-page-data-updated', (event) => { | |
if (navigated) { | |
navigated = false; | |
const channelHandle = getChannelHandle(); | |
const videoContainer = document.getElementById('movie_player'); | |
const isLiveStream = videoContainer?.querySelector('.ytp-live') || false; | |
video = videoContainer?.querySelector('video'); | |
if (channelHandle && video && !isLiveStream) { | |
applySavedSpeed(channelHandle, video); | |
setTimeout(() => video.addEventListener('ratechange', speedChangeListener), 250); // slight delay since youtube applies the speed from the previous video | |
} | |
} | |
}); | |
function speedChangeListener(event) { | |
const channelHandle = getChannelHandle(); | |
if (channelHandle) { | |
saveOrDeleteSpeed(channelHandle, event.target.playbackRate); | |
} else { | |
log('Could not find channel handle, current speed cannot be saved'); | |
} | |
}; | |
async function saveOrDeleteSpeed(channelHandle, speed) { | |
if (speed == 1) { | |
GM.deleteValue(channelHandle); | |
log(`Deleted playback speed for ${channelHandle}`); | |
} else if (speed != await GM.getValue(channelHandle)) { | |
GM.setValue(channelHandle, speed); | |
log(`Saved playback speed ${speed}x for ${channelHandle}`); | |
}; | |
} | |
async function applySavedSpeed(channelHandle, video) { | |
const channelSpeed = await GM.getValue(channelHandle); | |
if (channelSpeed) { | |
video.playbackRate = channelSpeed; | |
log(`Restored saved speed ${channelSpeed}x for ${channelHandle}`); | |
} | |
} | |
function getChannelHandle() { | |
const channelUrl = document.querySelector('#owner a')?.href; | |
return channelUrl ? channelUrl.substring(channelUrl.lastIndexOf('/') + 1) : null; | |
} | |
function log() { | |
console.debug(`[${GM.info.script.name}]`, ...arguments); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment