Last active
March 28, 2025 17:25
-
-
Save SanteriHetekivi/146a3340343e05d6b3f35699103965a9 to your computer and use it in GitHub Desktop.
Automatically plays the next YouTube short.
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 Shorts Auto Next | |
// @description Automatically plays the next YouTube short. | |
// @version 2024-03-02 | |
// @author Santeri Hetekivi | |
// @match https://www.youtube.com/shorts/* | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com | |
// @grant none | |
// @license Apache-2.0 | |
// ==/UserScript== | |
(function () { | |
'use strict'; | |
/** | |
* Get video element. | |
* @returns {HTMLVideoElement} The video element. | |
*/ | |
function getVideo() { | |
// Get all video elements with src attribute. | |
const videos = document.querySelectorAll("video[src]") | |
// Get elements length. | |
const videosLength = videos.length | |
// If there is only one video element | |
if (videosLength === 1) { | |
// init get video timeout counter. | |
getVideo.timeoutCounter = 0 | |
const video = videos[0] | |
if (!(video instanceof HTMLVideoElement)) { | |
throw new Error("Video is not a HTMLVideoElement!") | |
} | |
return video | |
} | |
// Else if no video elements found | |
else if (videosLength === 0) { | |
// Set timeout for getting video. | |
getVideo.timeout = setTimeout( | |
function () { | |
// Clear timeout. | |
clearTimeout(getVideo.timeout) | |
getVideo.timeout = null | |
return getVideo() | |
}, | |
// Timeout time is 1000ms * times this has been called.. | |
1000 * (++getVideo.timeoutCounter) | |
); | |
} | |
// Else if there are more than one video elements, throw error. | |
else { | |
throw new Error("Found " + videosLength + " video elements with src attribute!") | |
} | |
} | |
// Get and initialise video element. | |
const video = getVideo() | |
/** | |
* Init video element. | |
*/ | |
function initVideo() { | |
// Set autoplay to false. | |
video.autoplay = false | |
// Set loop to false. | |
video.loop = false | |
} | |
// Init video. | |
initVideo() | |
// Add event listener for ended event. | |
video.addEventListener( | |
"ended", | |
function () { | |
// Get next button. | |
const button = document.querySelector("#navigation-button-down button") | |
if (!(button instanceof HTMLButtonElement)) { | |
throw new Error("No next button found!") | |
} | |
// Click the next button. | |
button.click() | |
} | |
) | |
// Add event listener for progress event. | |
video.addEventListener( | |
"progress", | |
function () { | |
// Init video again, because Youtube resets video element. | |
initVideo() | |
} | |
) | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment