仮想と物理とエトセトラ

xRや物理とかごった煮の備忘録的技術ブログ

簡易翻訳機を作ってみる その5 翻訳結果を音声出力する

今回は前回の翻訳機の続きです。

xr-physics-work-etc.hatenablog.com

今回は、音声読み上げと、別言語を翻訳先とする翻訳を行います。
音声の読み上げでは、TextToSpeechを使用します。
TextToSpeechは、任意の文字列を音声出力するためのコンポーネントです。

docs.microsoft.com

翻訳先の変更は、DeepL APIで翻訳リクエストを行うためのtarget_langを切り替えることで実現します。

準備

音声出力する

まずは、前回のUnityProjectにTextToSpeechコンポーネントをアタッチします。
今回はTranslateResultゲームオブジェクトにアタッチしました。
f:id:napo909:20211031154826p:plain

TextToSpeechコンポーネントをアタッチすると、AudioSourceコンポーネントも一緒にアタッチされます。
TextToSpeechには2つのオプションがInspector上から設定できます。

  • Audio Source
    使用するAudioSourceコンポーネントを設定する。
  • Voice
    音声ソース(しゃべるための音源)を変更する

TextToSpeechコンポーネントのStartSpeaking(string)メソッドを使用することで、任意の文字列を音声出力することができます。

次に、音声出力有効/無効を切り替えるために、トグルボタンを配置します。
新しいトグルボタンをMRTK ToolBoxから選択し、シーン上に配置します。
f:id:napo909:20211031161946p:plain

今回は、アプリ起動時に音声出力を有効にしたいので、InteractableコンポーネントのIsToggledを有効にします。
f:id:napo909:20211031161906p:plain

次に、翻訳結果をTextToSpeechコンポーネントに渡すためのスクリプトSwitchAudioPlaying.csを作成し、Toggleボタンにアタッチします。

  • SwitchAudioPlaying.cs
クリックで展開
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.Toolkit.Audio;
using Microsoft.MixedReality.Toolkit.UI;

namespace SimplifiedTranslator
{
    public class SwitchAudioPlaying : MonoBehaviour
    {
        /// <summary>
        /// 翻訳機本体
        /// </summary>
        [SerializeField]
        Translator translator;
        
        /// <summary>
        /// 音声出力用コンポーネント
        /// </summary>
        [SerializeField]
        TextToSpeech textToSpeech;

        /// <summary>
        /// トグル状態取得用Interactableコンポーネント
        /// </summary>
        [SerializeField]
        Interactable interactable;

        // Start is called before the first frame update
        void Start()
        {
            if (interactable == null)
            {
                this.enabled = false;
            }
            translator.Finish_translate_event.AddListener(PlayTranslatedAudio);
        }

        /// <summary>
        /// 翻訳結果出力処理
        /// </summary>
        /// <param name="translateResult"></param>
        void PlayTranslatedAudio(string translateResult)
        {
            if (interactable.IsToggled)
            {
                textToSpeech.StartSpeaking(translateResult);
            }
        }

    }
}

f:id:napo909:20211031162600p:plain

Inspectorから対応するコンポーネントをアタッチすることで、翻訳結果取得時に、トグルボタンが有効な時には音声が出力されるようになりました。

翻訳先言語を変更する

これまでは英語にしか翻訳できなかったため、別言語にも翻訳できるようにします。
DeepL APIでは20種類以上の言語に翻訳することができます。

www.deepl.com

RadioButtonsオブジェクトをシーン上に配置し、InteractableToggleCollectionGridObjectCollectionをアタッチします。
そのオブジェクトの子として任意の数(今回は4つ)のラジオボタンを配置し、InteractableToggleCollectionコンポーネントに登録します。
GridObjectCollectionでは、ボタンを目的の並びになるようにパラメータを設定し、UnityEditor上からUpdate Collectionボタンを用いて整列します。
参考:

f:id:napo909:20211031162934p:plain f:id:napo909:20211031164347p:plain f:id:napo909:20211031163052p:plain f:id:napo909:20211031163113p:plain

次に、それぞれのボタンに言語情報を持たせるためにLangSettingコンポーネントを作成します。
このコンポーネントをそれぞれのラジオボタンにアタッチし、インスペクター上のプルダウンメニューから翻訳先の言語を設定します。

  • LangSetting.cs
クリックで展開
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace SimplifiedTranslator
{
    public enum TargetLang
    {
        JA,
        EN,
        ZH,
        DE,
    }

    public class LangSetting : MonoBehaviour
    {
        [SerializeField]
        TargetLang target_lang;

        public string GetTargetLang()
        {
            return target_lang.ToString();
        }
    }
}

f:id:napo909:20211031163421p:plain

次に、現在ラジオボタンで有効になっている言語を翻訳時に取得するために、GetLangSettingコンポーネントを作成し、その3で作成したTranslateTestを一部修正します。

  • GetLangSetting.cs
クリックで展開
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.Toolkit.UI;

namespace SimplifiedTranslator
{
    public class GetLangSetting : MonoBehaviour
    {
        [SerializeField]
        InteractableToggleCollection interactableToggleCollection;

        public string GetLangInfo() 
        {
            Interactable interactable = interactableToggleCollection.ToggleList[interactableToggleCollection.CurrentIndex];

            return interactable.GetComponent<LangSetting>().GetTargetLang();
        }
    }
}
  • TranslateTest.cs
クリックで展開
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using SimplifiedTranslator;
using TMPro;

namespace SimplifiedTranslator
{
    public class TranslateTest : MonoBehaviour
    {
        [SerializeField]
        TMP_InputField inputField;

        [SerializeField]
        TextMeshPro result;

        [SerializeField]
        Translator translator;

        /// <summary>
        /// 今回の追加点
        /// </summary>
        [SerializeField]
        GetLangSetting getLangSetting;


        // Start is called before the first frame update
        void Start()
        {
            translator.Finish_translate_event.AddListener(ShowTranslateResult);
        }

        // Update is called once per frame
        void Update()
        {

        }

        public void StartTranslate()
        {
            Debug.Log("Start Translate");
            // 今回の変更点。getLangSettingを使用することで、ラジオボタンで選択された言語をターゲットに翻訳する
            // translator.GetTranslatorResult(inputField.text, "EN");
            translator.GetTranslatorResult(inputField.text, getLangSetting.GetLangInfo());
        }

        public void ShowTranslateResult(string translated_text)
        {
            result.SetText(translated_text);
        }
    }
}

作成した、GetLangSettingコンポーネントRadioButtonsオブジェクトにアタッチし、TranslateTestコンポーネントに参照させます。

f:id:napo909:20211031164158p:plain f:id:napo909:20211031164300p:plain

これで、ラジオボタンを用いて、目的の言語に翻訳させる準備ができました。

動作確認

音声出力はアルファベットの出力の際しか取得できず、ドイツ語も発音が正しいかわかりませんが、英語では正しそうな音声出力結果を取得することができました。
中国語への翻訳の場合は、対応する文字をTextMeshProのフォントに登録していなかったため正しく表示されていません。今後対応する必要があります。

これで、少なくとも日本語→英語への翻訳結果を音声出力することができました。