LoginSignup
6
3

More than 1 year has passed since last update.

ビデオ通話に翻訳機能を追加する方法

Posted at

この記事はAgora社の公式ブログから翻訳機能に関する記事を紹介します。
AgoraWebSDKとGoogleCloudを使用してリアルタイム翻訳サービスを作成する方法を学びます。
原文はBuild a Live Translated Transcriptions Service in Your Video Call Web Appに公開されています。

サンプルコードはGithubも公開されています。

はじめに

グローバルにビジネスを行うことは、ほぼすべての企業の目標です。国際レベルにスケールアップする機会は利益を増やすことができますが、世界中のクライアントやパートナーと通信するために複数の言語の知識が必要になる場合があります。

多言語のビデオ会議の翻訳を手伝ってくれる通訳を雇うことは、煩わしく、会議が必要以上に長くなる可能性があるため、実用的ではありません。また、一部の情報の機密を保持することもできます。

このチュートリアルでは、JavaScriptのWeb Speech API、Agora Web SDK、Agora RTM SDK、およびGoogle Cloud Translation APIを使用して、音声からテキストへの文字起こしと翻訳をサポートするWebアプリケーションを構築します。

build-a-live-translated-transcriptions-service-within-your-video-call-web-1.png

前提条件

  • JavaScript、JQuery、Bootstrap、およびFontAwesomeに関する基本的な知識
  • Agora開発者アカウント
  • AgoraWebSDKおよびAgoraRTMSDKの使用方法の知識
  • GoogleCloudアカウント
  • RESTAPIからリクエストを作成してレスポンスを受信する方法の知識

プロジェクトの設定

既存のプロジェクトであるビデオ通話Webアプリ内での独自の文字起こしサービスの構築に基づいて構築します。
このプロジェクトのGithubリポジトリのクローンを作成することから始めることができます。これで、次のようなプロジェクトが作成されます。
build-a-live-translated-transcriptions-service-within-your-video-call-web-2.png

ここで、メモ関連のHTMLと余分なボタンを削除します。上記のコードの機能を理解するのが難しい場合は、このチュートリアルを参照してください。

また、ビデオ通話アプリケーションにビデオとオーディオのミュートとミュート解除のコードを追加しました。Agoraのドキュメントから、ミュートとミュート解除の詳細を学ぶことができます。

これで、完全に機能する文字起こしサービスと、ミュートおよびミュート解除機能が利用できるようになりました。

アプリケーションにリアルタイム翻訳を追加する

次に、既存の入力フィールドの行の下にあるHTMLファイルに次のコードを追加し、ユーザーがGoogleCloudプロジェクトのAPIキーを入力するためのオプションを追加します。

<div class="row mt-3 mb-3">
        <div class="col-sm">
          <p class="join-info-text">Google Cloud API Key</p>
          <input id="gcpKey" type="text" placeholder="Enter Google Cloud API Key" required class="form-control">
        </div>
        <div class="col-sm">
          <label for="format">Select a Language you Understand</label>
          <select class="form-control" name="transcriptionLang" id="transcriptionLang">
            <option value="af">Afrikaans</option>
            <option value="sq">Albanian</option>
            <option value="ar">Arabic</option>
            <option value="hy">Armenian</option>
            <option value="ca">Catalan</option>
            <option value="zh">Chinese</option>
            <option value="hr">Croatian</option>
            <option value="cs">Czech</option>
            <option value="da">Danish</option>
            <option value="nl">Dutch</option>
            <option value="en" selected>English</option>
            <option value="eo">Esperanto</option>
            <option value="fi">Finnish</option>
            <option value="fr">French</option>
            <option value="de">German</option>
            <option value="el">Greek</option>
            <option value="ht">Haitian Creole</option>
            <option value="hi">Hindi</option>
            <option value="hu">Hungarian</option>
            <option value="is">Icelandic</option>
            <option value="id">Indonesian</option>
            <option value="it">Italian</option>
            <option value="ja">Japanese</option>
            <option value="ko">Korean</option>
            <option value="la">Latin</option>
            <option value="lv">Latvian</option>
            <option value="mk">Macedonian</option>
            <option value="no">Norwegian</option>
            <option value="pl">Polish</option>
            <option value="pt">Portuguese</option>
            <option value="pt-br">Portuguese (Brazil)</option>
            <option value="ro">Romanian</option>
            <option value="ru">Russian</option>
            <option value="sr">Serbian</option>
            <option value="sk">Slovak</option>
            <option value="es">Spanish</option>
            <option value="es-es">Spanish (Spain)</option>
            <option value="es-us">Spanish (United States)</option>
            <option value="sw">Swahili</option>
            <option value="sv">Swedish</option>
            <option value="ta">Tamil</option>
            <option value="th">Thai</option>
            <option value="tr">Turkish</option>
            <option value="vi">Vietnamese</option>
            <option value="cy">Welsh</option>
          </select>
        </div>
</div>

build-a-live-translated-transcriptions-service-within-your-video-call-web-3.png

Google CloudTranslationAPIキーを作成する

  • クラウドコンソールで、サービスアカウントの作成ページに移動します。
  • プロジェクトを選択します。
  • 「Service account name」フィールドに名前を入力します。クラウドコンソールは、この名前に基づいてService account IDに入力します。
  • [Service account description]フィールドに説明を入力します。例:Agora LiveTranslatedTranscription
  • [Create and Continue]をクリックします。

build-a-live-translated-transcriptions-service-within-your-video-call-web-4.png

  • [Select a role]フィールドをクリックして、 Cloud Translation API Adminのroleを選択します。

build-a-live-translated-transcriptions-service-within-your-video-call-web-5.png

  • [Continue]をクリックします。
  • [Done]をクリックして、サービスアカウントの作成を終了します。
  • ここからCloudTranslationAPIを有効にします。

build-a-live-translated-transcriptions-service-within-your-video-call-web-6.png

  • 左側のサイドバーの[Credentials]タブをクリックし、[Create Credentials]をクリックします。
  • 生成されたAPIキーを作成してコピーします。

build-a-live-translated-transcriptions-service-within-your-video-call-web-7.png

メイン機能の実装

基本構造がレイアウトされ、キーが生成されたので、翻訳サービスに機能を追加し始めることができます。最初は難しいように見えるかもしれませんが、GCPの公式ドキュメントに従えば、それは簡単なことです。

以下のコードは、ユーザーが入力したGCPキーとユーザーが希望する文字起こし言語を取り込みます。ユーザーが話すのをやめるとすぐに、JavaScriptのWeb Speech APIを使用して、選択した言語で単語が書き起こされます。

これと同じメッセージが、AgoraRTMSDKを介してすべてのユーザーに話者の言語で送信されます。このメッセージを受信すると、受信者の優先言語を確認し、Google Translate APIを使用して、送信された元のメッセージをユーザーが理解できるテキストに変換します。このように、リモートユーザーがローカルユーザーとは異なる言語を使用している場合でも、ロジックは期待どおりに機能します。

...
recognition.start();
            // Start transcribing and translating
            var gcpKey = $("#gcpKey").val();
            var transcriptionLang = $('#transcriptionLang').val();
            recognition.onresult = function (event) {
                var current = event.resultIndex;
                var transcript = event.results[current][0].transcript;
                transContent = transContent + transcript;
                singleMessage = transContent;

                // Write code to send, process and show translated transcription to host.
                rtmText = {
                    singleMessage: singleMessage,
                    senderLang: $('#transcriptionLang').val(),
                    time: new Date().toLocaleString("en-US", { year: 'numeric', month: 'long', day: 'numeric', hour12: true, hour: 'numeric', minute: 'numeric', second: 'numeric' })
                };
                msg = {
                    messageType: 'TEXT',
                    rawMessage: undefined,
                    text: JSON.stringify(rtmText)
                };
                channel.sendMessage(msg).then(() => {
                    console.log("Message sent successfully.");
                    console.log("Your message was: " + rtmText.singleMessage + " by " + accountName + " in the following language: " + rtmText.senderLang + " sent at: " + rtmText.time);
                    if (rtmText.senderLang == transcriptionLang) {
                        $("#actual-text").append("<br> <b>Speaker:</b> " + accountName + "<br> <b>Message:</b> " + rtmText.singleMessage + "<br> <b>Sent On:</b> " + rtmText.time + "<br>");
                        transContent = '';
                    } else {
                        var xhr = new XMLHttpRequest();
                        xhr.open("POST", `https://www.googleapis.com/language/translate/v2?key=${gcpKey}&source=${rtmText.senderLang}&target=${transcriptionLang}&callback=translateText&q=${singleMessage}`, true);
                        xhr.send();
                        xhr.onload = function () {
                            if (this.status == 200) {
                                var data = JSON.parse(this.responseText);
                                console.log(data.data.translations[0].translatedText);
                                $("#actual-text").append("<br> <b>Speaker:</b> " + accountName + "<br> <b>Message:</b> " + data.data.translations[0].translatedText + "<br> <b>Sent On:</b> " + rtmText.time + "<br>");
                                transContent = '';
                            } else {
                                var data = JSON.parse(this.responseText);
                                console.log(data);
                            }
                        };
                    }
                }).catch(error => {
                    console.log("Message wasn't sent due to an error: ", error);
                });
            };
            // Receive RTM Channel Message
            channel.on('ChannelMessage', ({
                text
            }, senderId) => {
                // Write code to receive, process and show translated transcription to all users.
                rtmText = JSON.parse(text);
                console.log("Message received successfully.");
                console.log("The message is: " + rtmText.singleMessage + " by " + senderId + " in the following language: " + rtmText.senderLang + " sent at: " + rtmText.time);
                var xhr = new XMLHttpRequest();
                xhr.open("POST", `https://www.googleapis.com/language/translate/v2?key=${gcpKey}&source=${rtmText.senderLang}&target=${transcriptionLang}&callback=translateText&q=${rtmText.singleMessage}`, true);
                xhr.send();
                xhr.onload = function () {
                    if (this.status == 200) {
                        var data = JSON.parse(this.responseText);
                        console.log(data.data.translations[0].translatedText);
                        $("#actual-text").append("<br> <b>Speaker:</b> " + senderId + "<br> <b>Message:</b> " + data.data.translations[0].translatedText + "<br> <b>Sent On:</b> " + rtmText.time + "<br>");
                        transContent = '';
                    } else {
                        var data = JSON.parse(this.responseText);
                        console.log(data);
                    }
                };
            });
...

build-a-live-translated-transcriptions-service-within-your-video-call-web-8.png

これで、Webビデオ通話アプリケーション内で多言語の文字起こしサービスを正常に作成できました。

こちらから実際のコードのデモを確認できます。

最後に

agora.ioに関するお問い合わせはこちらから
スクリーンショット 0001-08-15 13.41.56.png

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3