YouTube Subtitle Auto-Translator

自動的にYouTubeの字幕を日本語に翻訳します

目前為 2024-06-10 提交的版本,檢視 最新版本

// ==UserScript==
// @name         YouTube Subtitle Auto-Translator
// @namespace    http://tampermonkey.net/
// @version      0.7
// @description  自動的にYouTubeの字幕を日本語に翻訳します
// @author       Aoi
// @match        https://www.youtube.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const googleTranslateUrl = 'https://translate.google.com/?sl=auto&tl=ja&text=';

    // DOMに要素が現れるのを待つ関数
    function waitForElement(selector, callback) {
        const element = document.querySelector(selector);
        if (element) {
            callback(element);
        } else {
            setTimeout(() => waitForElement(selector, callback), 500);
        }
    }

    // Google翻訳のウェブ版を使用してテキストを翻訳する関数
    async function translateText(text) {
        const response = await fetch(googleTranslateUrl + encodeURIComponent(text));
        const html = await response.text();
        const parser = new DOMParser();
        const doc = parser.parseFromString(html, 'text/html');
        const translatedText = doc.querySelector('.result-container').innerText;
        return translatedText;
    }

    // 5秒後に 'C'キーを送信して字幕をオンにする関数
    function turnOnSubtitles() {
        setTimeout(() => {
            document.dispatchEvent(new KeyboardEvent('keydown', {'key': 'C', 'keyCode': 67, 'code': 'KeyC', 'which': 67, 'bubbles': true}));
        }, 5000);
    }

    // 字幕を監視し、翻訳する関数
    function observeSubtitles() {
        const observer = new MutationObserver(async mutations => {
            for (const mutation of mutations) {
                if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                    const subtitleElement = mutation.addedNodes[0];
                    const subtitleText = subtitleElement.innerText;

                    // テキストが日本語でない場合のみ翻訳する
                    if (subtitleText && !/[\u3040-\u30FF\uFF66-\uFF9F]/.test(subtitleText)) {
                        const translatedText = await translateText(subtitleText);
                        subtitleElement.innerText = translatedText;
                    }
                }
            }
        });

        waitForElement('.captions-text', subtitlesContainer => {
            observer.observe(subtitlesContainer, { childList: true, subtree: true });
        });
    }

    // ビデオプレーヤーが準備できたら字幕の監視を開始する
    waitForElement('.html5-video-container', () => {
        turnOnSubtitles();
        observeSubtitles();
    });
})();