YouTube Shorts Auto Next

Automatically plays the next YouTube short.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==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
// @namespace https://greasyfork.org/users/164021
// ==/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()
        }
    )
})();