YouTube Shorts Auto Next

Automatically plays the next YouTube short.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 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()
        }
    )
})();