CaptionPopで英語字幕しかない動画でも日本語を表示できるようにしてみた

CaptionPopはYouTubeの字幕を２つ同時に表示できる便利なサイトです。

https://www.captionpop.com/

![captionpop](https://i.gyazo.com/72b0a517e4dab8c9983953725ea08644.png)

英語＋日本語など異なる言語の字幕を同時に確認することができます。

ただ、もともと英語字幕しか用意されていない場合は「このビデオの字幕は英語のみ利用可能です。」と表示されて同時表示ができません

英語字幕しかない動画でも日本語を同時に表示する方法を考えてみました。

#方法１：YouTubeのAPIを使用する
もともとYouTubeには字幕を翻訳して表示する機能がついています。

```
https://www.youtube.com/api/timedtext?lang=en&name=&v=動画のID&tlang=ja
```

翻訳済みの字幕はAPIを使って簡単に取得することができます。

APIで取得した翻訳済み字幕を英語字幕の下にしてやれば同時に２つの字幕を表示できます

```javascript
(async function () {
    let tcap = await fetch(`https://www.youtube.com/api/timedtext?lang=en&name=&v=${location.pathname.split("/")[2]}&tlang=ja`)
    tcap = await tcap.text();
    tcap = new DOMParser().parseFromString(tcap, "text/xml"); // XMLをパースする
    tcap = tcap.getElementsByTagName("text"); // 字幕が含まれるタグの配列
    addCaption(tcap);
})();

function addCaption(tcap) {
    let captions = document.getElementsByClassName("subtitle-transcription");

    if (captions.length !== tcap.length) return setTimeout(addCaption, 100, tcap); // CaptionPopの字幕表示を待つ

    for (let i = 0; i < captions.length; i++) {
        captions[i].innerHTML += "<br>" + tcap[i].innerHTML; // 改行して翻訳済み字幕を挿入
    }
}
```

これをTampermonkeyなどの拡張機能を使って読み込めばいいだけです。

#方法２：翻訳APIで全部翻訳する
方法１が思いつかなくて試した方法

Google翻訳APIが無料で使えるみたいだった
https://qiita.com/satto_sann/items/be4177360a0bc3691fdf
のでこれを使ってみました

```javascript

(function (c) {

    async function translate(text) {
        let result = await fetch(`https://api.craftpot.work/translate?source=en&target=ja&text=${text}`);
        result = await result.text();
        return (JSON.parse(result).text);
    }

    async function addCaption() {
        const captions = document.getElementsByClassName("subtitle-transcription");

        if (captions.length !== 0 && !!captions[c]) {
            captions[c].innerHTML += "<br>" + await translate(captions[c].innerText);
            c++;
            addCaption();
        } else {
            setTimeout(addCaption, 500);
        }
    }

    addCaption();
})(0);
```

クロスオリジンでfetchできるようにしたAPIにリクエストを投げて全部翻訳していくというもの。

全部翻訳し終わるまでに時間がかかるし、字幕が300行あったらリクエスト300回投げるので良い方法とは言えませんよね。

一応動きますが・・・

#Userscript化したもの
```javascript
// ==UserScript==
// @name         CaptionPop Trans
// @namespace    ayeee
// @version      1.0
// @description  try to take over the world!
// @author       me
// @match        https://www.captionpop.com/videos/*
// @grant        none
// ==/UserScript==

(function () {

    (async function () {
        let tcap = await fetch(`https://www.youtube.com/api/timedtext?lang=en&name=&v=${location.pathname.split("/")[2]}&tlang=ja`)
        tcap = await tcap.text();
        tcap = new DOMParser().parseFromString(tcap, "text/xml"); // XMLをパースする
        tcap = tcap.getElementsByTagName("text"); // 字幕が含まれるタグの配列
        addCaption(tcap);
    })();

    function addCaption(tcap) {
        let captions = document.getElementsByClassName("subtitle-transcription");

        if (captions.length !== tcap.length) return setTimeout(addCaption, 100, tcap); // CaptionPopの字幕表示を待つ

        for (let i = 0; i < captions.length; i++) {
            captions[i].innerHTML += "<br>" + tcap[i].innerHTML; // 改行して翻訳済み字幕を挿入
        }
    }

})();
```

![ScreenShot_20200420160801.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576748/0b5c60fb-d74a-c6c2-b453-d1d3c5e1d800.png)



参考になれば幸いです