🎉 欢迎访问GreasyFork.Org 镜像站!本镜像站由公众号【爱吃馍】搭建,用于分享脚本。联系邮箱📮

Greasy fork 爱吃馍镜像

YouTube Auto Reload When Video unavailable

Reloads YouTube when a video fails. Active tab only. May need to press F5 once on first visit.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

You will need to install an extension such as Tampermonkey to install this script.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

// ==UserScript==
// @name         YouTube Auto Reload When Video unavailable 
// @name:zh-TW   YouTube 影片無法播放自動重整
// @name:ja      YouTubeの動画が再生できません時に自動リロード
// @namespace    https://example.com/
// @version      2.6
// @description  Reloads YouTube when a video fails. Active tab only. May need to press F5 once on first visit.
// @description:zh-TW 卡住的 YouTube 影片自動重新整理(僅限活頁籤)。首次可能需手動按一次 F5。
// @description:ja YouTubeの動画が読み込めない時に自動リロードします(アクティブタブのみ)。初回はF5が必要な場合があります。
// @match        https://www.youtube.com/watch*
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    let isReloading = false;
    let observer = null;

    // 檢查是否是「直播尚未開始」狀態
    function isLiveUpcomingFromPlayerResponse() {
        try {
            const ytData = window.ytInitialPlayerResponse;
            const status = ytData?.playabilityStatus?.status;
            return status === 'LIVE_STREAM_OFFLINE';
        } catch (e) {
            return false;
        }
    }

    const checkVideoStatus = () => {
        if (document.hidden) return true;

        if (isLiveUpcomingFromPlayerResponse()) {
            return true; // 直播尚未開始 → 不 reload
        }

        const video = document.querySelector('video');
        const errorBox = document.querySelector('.ytp-error, .ytp-error-content-wrap');

        if (
            (errorBox && errorBox.offsetParent !== null) ||
            !video ||
            (video.currentTime === 0 && video.paused)
        ) {
            return false;
        }

        return true;
    };

    const tryReload = () => {
        if (isReloading) return;
        isReloading = true;
        location.reload();
    };

    const startObserver = () => {
        if (observer) return;

        const target = document.body;
        if (!target) return;

        observer = new MutationObserver(() => {
            if (!checkVideoStatus()) tryReload();
        });

        observer.observe(target, {
            childList: true,
            subtree: true
        });

        if (!checkVideoStatus()) tryReload();
    };

    const stopObserver = () => {
        if (observer) {
            observer.disconnect();
            observer = null;
        }
    };

    window.addEventListener('load', () => {
        startObserver();
    });

    document.addEventListener('visibilitychange', () => {
        if (!document.hidden && !checkVideoStatus()) {
            tryReload();
        }
    });
})();