YouTube Đặt lại bản nhạc âm thanh

Ghi đè việc sử dụng tự động các bản nhạc âm thanh đã được tạo và dịch trên video YouTube. Đặt lại về âm thanh gốc.

// ==UserScript==
// @name            YouTube Audiotrack Reset
// @name:zh-TW      YouTube 音軌重置
// @name:zh-HK      YouTube 音軌重置
// @name:zh-CN      YouTube 音轨重置
// @name:ja         YouTube オーディオトラックリセット
// @name:kr         YouTube 오디오트랙 리셋
// @name:ar         YouTube إعادة تعيين المسار الصوتي
// @name:bg         YouTube Нулиране на аудио пистата
// @name:cs         YouTube Reset audio stopy
// @name:da         YouTube Nulstil lydspor
// @name:de         YouTube Audiotrack zurücksetzen
// @name:tel        YouTube ఆడియో ట్రాక్ రీసెట్
// @name:es         YouTube Restablecer pista de audio
// @name:en         YouTube Audiotrack Reset
// @name:fr         YouTube Réinitialiser la piste audio
// @name:fr-CA      YouTube Réinitialiser la piste audio
// @name:he         YouTube לאפס את מסלול האודיו
// @name:hu         YouTube Audio nyomvonal visszaállítása
// @name:id         YouTube Reset trek audio
// @name:it         YouTube Reimposta traccia audio
// @name:ko         YouTube 오디오 트랙 재설정
// @name:nb         YouTube Tilbakestill lydspor
// @name:nl         YouTube Audiotrack resetten
// @name:pl         YouTube Resetuj ścieżkę audio
// @name:pt-BR      YouTube Resetar trilha de áudio
// @name:ro         YouTube Resetare pistă audio
// @name:ru         YouTube Сброс аудиотрека
// @name:sk         YouTube Obnovenie zvukovej stopy
// @name:sr         YouTube Resetovanje audio trake
// @name:sv         YouTube Återställ ljudspår
// @name:th         YouTube รีเซ็ตแทร็กเสียง
// @name:tr         YouTube Ses parçasını sıfırlama
// @name:uk         YouTube Скинути аудіотрек
// @name:ug         YouTube ئاۋاز يېزىلىشنى قايتا توغرىلاش
// @name:vi         YouTube Đặt lại bản nhạc âm thanh
// @version         0.1.5
// @description     Overrides automatic use of generated, translated audiotracks on YouTube videos. Resets to original audio.
// @description:zh-TW 覆蓋YouTube視頻上自動生成的翻譯音軌。重置為原始音軌。
// @description:zh-HK 覆蓋YouTube視頻上自動生成的翻譯音軌。重置為原始音軌。
// @description:zh-CN 覆盖YouTube视频上自动生成的翻译音轨。重置为原始音轨。
// @description:ja YouTube動画の自動生成された翻訳音声トラックを上書きします。元の音声にリセットします。
// @description:kr YouTube 비디오에서 자동으로 생성된 번역된 오디오 트랙을 덮어씁니다. 원래 오디오로 재설정합니다.
// @description:ar يتجاوز الاستخدام التلقائي للمسارات الصوتية المترجمة المولدة على مقاطع الفيديو الخاصة بـ YouTube. يعيد تعيين الصوت الأصلي.
// @description:bg Пренаписва автоматичното използване на генерирани преведени аудиотреки в YouTube видеа. Нулира до оригиналния звук.
// @description:cs Přepisuje automatické použití generovaných přeložených zvukových stop u videí YouTube. Resetuje na původní zvuk.
// @description:da Omgår automatisk brug af genererede, oversatte lydspor på YouTube-videoer. Nulstiller til original lyd.
// @description:de Überschreibt die automatische Verwendung von generierten, übersetzten Audiotracks in YouTube-Videos. Setzt auf den Originalton zurück.
// @description:tel YouTube వీడియోలపై స్వయంచాలకంగా ఉత్పత్తి చేసిన అనువాద ఆడియో ట్రాక్స్‌ని ఓవర్‌రైడ్ చేస్తుంది. మౌలిక ఆడియోకి రీసెట్ చేస్తుంది.
// @description:es Sobrescribe el uso automático de pistas de audio generadas y traducidas en videos de YouTube. Restablece el audio original.
// @description:en Overrides automatic use of generated, translated audiotracks on YouTube videos. Resets to original audio.
// @description:fr Remplace l'utilisation automatique des pistes audio générées et traduites dans les vidéos YouTube. Réinitialise l'audio original.
// @description:fr-CA Remplace l'utilisation automatique des pistes audio générées et traduites dans les vidéos YouTube. Réinitialise l'audio original.
// @description:he עוקף את השימוש האוטומטי במסלולי אודיו מתורגמים שנוצרו בסרטוני YouTube. מחזיר לאודיו המקורי.
// @description:hu Felülírja a YouTube videók automatikusan generált, lefordított audiótracks használatát. Visszaállítja az eredeti hangot.
// @description:id Menggantikan penggunaan otomatis trek audio terjemahan yang dihasilkan pada video YouTube. Mengatur ulang ke audio asli.
// @description:it Sovrascrive l'uso automatico delle tracce audio tradotte generate nei video di YouTube. Ripristina l'audio originale.
// @description:ko YouTube 비디오에서 자동 생성된 번역된 오디오 트랙의 자동 사용을 덮어씁니다. 원래 오디오로 재설정합니다.
// @description:nb Omgår automatisk bruk av genererte, oversatte lydspor på YouTube-videoer. Tilbakestiller til original lyd.
// @description:nl Overschrijft automatisch gebruik van gegenereerde, vertaalde audiotracks op YouTube-video's. Zet terug naar het originele geluid.
// @description:pl Nadpisuje automatyczne użycie generowanych, przetłumaczonych ścieżek dźwiękowych w filmach YouTube. Resetuje do oryginalnego dźwięku.
// @description:pt-BR Substitui o uso automático de faixas de áudio geradas e traduzidas nos vídeos do YouTube. Restaura para o áudio original.
// @description:ro Suprascrie utilizarea automată a pieselor audio traduse generate pe videoclipurile YouTube. Resetează la audio original.
// @description:ru Перезаписывает автоматическое использование сгенерированных переведенных аудиотреков в видео на YouTube. Возвращает к оригинальному аудио.
// @description:sk Prepisuje automatické použitie generovaných preložených zvukových stôp na videách YouTube. Resetuje na pôvodný zvuk.
// @description:sr Prepisuje automatsko korišćenje generisanih, prevedenih audio traka na YouTube video zapisima. Vraća na originalni zvuk.
// @description:sv Överskriver automatisk användning av genererade översatta ljudspår på YouTube-videor. Återställer till original ljud.
// @description:th แทนที่การใช้แทร็กเสียงที่แปลและสร้างโดยอัตโนมัติในวิดีโอ YouTube รีเซ็ตเป็นเสียงต้นฉบับ
// @description:tr YouTube videolarındaki otomatik olarak oluşturulmuş, çevrilmiş ses izlerinin kullanımını geçersiz kılar. Orijinal sesine sıfırlar.
// @description:uk Перезаписує автоматичне використання згенерованих, переведених аудіотреків на відео YouTube. Скидає до оригінального аудіо.
// @description:ug يۇتۇب ۋىدىئولارىدىكى ئاپتوماتىك تەرجىمە قىلىنغان، ياراتىلغان ئاۋازلارنى ئايرىپ قويىدۇ. ئەسلى ئاۋازغا قايتۇرۇلىدۇ.
// @description:vi Ghi đè việc sử dụng tự động các bản nhạc âm thanh đã được tạo và dịch trên video YouTube. Đặt lại về âm thanh gốc.
// @author          PolyMegos (https://github.com/polymegos)
// @namespace       https://github.com/polymegos/yt-original-audiotrack/
// @supportURL      https://github.com/polymegos/yt-original-audiotrack/issues
// @license         MIT
// @match           *://www.youtube.com/*
// @match           *://www.youtube-nocookie.com/*
// @match           *://m.youtube.com/*
// @match           *://music.youtube.com/*
// @grant           none
// @run-at          document-start
// @compatible      firefox
// @compatible      edge
// @compatible      safari
// ==/UserScript==

(function() {
    'use strict';

    function redirectToDesktop() {
        // Check if we're on m.youtube.com or in a mobile setting
        const isMobile = window.location.hostname === 'm.youtube.com' || 
                                (window.location.hostname === 'www.youtube.com' && 
                                (document.documentElement.classList.contains('mobile')));
        // Look whether desktop param already in URL
        const hasDesktopParam = window.location.search.includes('app=desktop');
        if (isMobile && !hasDesktopParam) {
            // Appending desktop parameter for new URL
            let newUrl = window.location.href;
            if (newUrl.includes('?')) {
                newUrl += '&app=desktop';
            } else {
                newUrl += '?app=desktop';
            }
            // Redirect to desktop version
            console.log('Redirecting to desktop version of YouTube...');
            window.location.href = newUrl;
            return true; // redirect
        }
        return false; // no redirect needed
    }

    // Wait for an element to appear in the DOM
    function waitForElement(selector, timeout = 10000) {
        return new Promise((resolve, reject) => {
            const element = document.querySelector(selector);
            if (element) return resolve(element);
            const observer = new MutationObserver((mutations, obs) => {
                const target = document.querySelector(selector);
                if (target) {
                    obs.disconnect();
                    resolve(target);
                }
            });
            observer.observe(document.body, { childList: true, subtree: true });
            setTimeout(() => {
                observer.disconnect();
                reject(new Error(`Timeout: Element ${selector} not found within ${timeout}ms`));
            }, timeout);
        });
    }

    // Simulate a click on the given element
    function clickElement(element) {
        if (element) {
            element.click();
        }
    }

    // Wait until no ad shown
    function waitForNoAds(timeout = 10000) {
        return new Promise((resolve, reject) => {
            const player = document.querySelector('.html5-video-player');
            if (!player || !player.classList.contains('ad-showing')) return resolve();
            const observer = new MutationObserver((mutations, obs) => {
                if (!player.classList.contains('ad-showing')) {
                    obs.disconnect();
                    resolve();
                }
            });
            observer.observe(player, { attributes: true, attributeFilter: ['class'] });
            setTimeout(() => {
                observer.disconnect();
                reject(new Error('Timeout: Ad still showing.'));
            }, timeout);
        });
    }

    // Main function to reset the audiotrack
    async function checkAudiotrack() {
        try {
            if (redirectToDesktop()) {
                return; // Early return to redirect to desktop view
            }

            // Wait for the video element and ensure no ad is playing
            await waitForElement('video');
            await waitForNoAds();

            // Open the settings menu
            const settingsButton = await waitForElement('.ytp-settings-button');
            clickElement(settingsButton);
            const settingsMenu = await waitForElement('.ytp-popup.ytp-settings-menu');

            // Find and click the "Audiotrack" item
            const audioTrackItem = Array.from(settingsMenu.querySelectorAll('.ytp-menuitem'))
                .find(item => item.textContent.includes('Audiotrack'));

            if (audioTrackItem) {
                clickElement(audioTrackItem);

                // Wait for the audiotrack submenu to appear
                const audioTrackMenu = await waitForElement('.ytp-popup.ytp-settings-menu');

                // Click the "Original" option
                const originalOption = Array.from(audioTrackMenu.querySelectorAll('.ytp-menuitem'))
                    .find(item => item.textContent.toLowerCase().includes('original'));

                if (originalOption) {
                    clickElement(originalOption);
                } else {
                    console.warn('"Original" audiotrack not found.');
                }
                // Close settings menu
                clickElement(settingsButton);
            } else {
                console.warn('Audiotrack menu not found.');
                // Close half-open settings menu
                clickElement(settingsButton);
            }
        } catch (error) {
            console.error('Error in script:', error);
        }
    }

    // Initial trigger on page load
    checkAudiotrack();

    // Re-run the script after SPA navigation events (when switching videos)
    document.addEventListener('yt-navigate-finish', () => {
        checkAudiotrack();
    });
})();