Youtube Subtitle From Romaji to Hiragana

Translate the romaji subtitle to hiragana

目前为 2021-07-10 提交的版本。查看 最新版本

// ==UserScript==
// @name         Youtube Subtitle From Romaji to Hiragana
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Translate the romaji subtitle to hiragana
// @author       CY Fung
// @match        https://www.youtube.com/*
// @icon         https://www.google.com/s2/favicons?domain=youtube.com
// @require      https://unpkg.com/[email protected]/umd/wanakana.min.js?charset=utf-8
// ==/UserScript==

(function() {
    'use strict';

    if(!window.WeakRef) throw 'This script only supports the latest browsers.';

    let cid, mto, elmWR;

    function targetCaptionWindow(pElm){

        if(pElm.style.width && pElm.style.marginLeft && pElm.style.left=='50%'){
            Promise.resolve(pElm).then(pElm=>{

                pElm.style.width='';
                pElm.style.transform='scaleX(0.8)';
                return pElm;
            }).then(pElm=>{
                requestAnimationFrame(()=> {
                    let w=pElm.offsetWidth+20
                    pElm.style.width=w+'px';
                    pElm.style.marginLeft= (-w/2).toFixed(2) +'px';
                } )
            })
        }
    }

    function mtoFunc(mutations, observer){


        for(const s of elmWR.deref().querySelectorAll('span.ytp-caption-segment')){


            let oldText=s.textContent||""
            if(/^[\x20-\x7E]+$/.test(oldText) && /[a-zA-Z]/.test(oldText)){

                let newText = oldText.split(/([^a-zA-Z]+)/).map((str,i)=>{

                    if(i%2) return str;
                    return window.wanakana.toKana(str)
                }).join('')

                if(newText !== oldText && !/[a-zA-Z]/.test(newText) ){

                    newText = newText
                        .replace(/[\!\?\,]/g,(_)=> String.fromCharCode(_.charCodeAt(0)+(0xFF1F-0x003F)))
                        .replace(/([\u3040-\u309F\u30A0-\u30FF])[\u3040-\u309F\u30A0-\u30FF\s]+([\u3040-\u309F\u30A0-\u30FF])/g,(_,a,b)=>_.replace(/\s+/g,' '))
                        .replace(/([\u3040-\u309F\u30A0-\u30FF])\s+([\uFF01-\uFF5E]+)/g,(_,a,b)=>a+b)
                    .replace(/([\x20-\x7E]+)([\u3040-\u309F\u30A0-\u30FF]+)/g,(_,a,b)=>a+' '+b)
                    .replace(/([\u3040-\u309F\u30A0-\u30FF]+)([\x20-\x7E]+)/g,(_,a,b)=>a+' '+b)
                    .replace(/ +/g,' ')


                    s.textContent = newText;

                    let pElm=s;
                    while(pElm && pElm.parentNode){

                        if(pElm.className.indexOf('caption-window')>=0) {

                            targetCaptionWindow(pElm);

                            break;
                        }
                        pElm=pElm.parentNode;
                    }


                }

            }

        }


    }

    function onNavigationEnd(){

        if(!/https\:\/\/www\.youtube\.com\/watch?.*v=[^\?\&]+/.test(location.href))return;


        if(cid) cid=clearInterval(cid);
        if(mto) {
            mto.takeRecords()
            mto.disconnect()
            mto=null;
        }

        if(elmWR) {
            elmWR=null;
        }


        cid=setInterval(()=>{

            let s=document.querySelector('#ytp-caption-window-container');
            if(!s)return;

            cid=clearInterval(cid);

            elmWR = new window.WeakRef(s);

            mto = new MutationObserver(mtoFunc);

            mto.observe(elmWR.deref(),{subtree: true, childList: true, attributes:false});

        },400)


    }



    window.addEventListener("yt-navigate-finish", onNavigationEnd)

    // Your code here...
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址