簡易翻訳機を作ってみる その5 翻訳結果を音声出力する
今回は前回の翻訳機の続きです。
xr-physics-work-etc.hatenablog.com
今回は、音声読み上げと、別言語を翻訳先とする翻訳を行います。
音声の読み上げでは、TextToSpeechを使用します。
TextToSpeechは、任意の文字列を音声出力するためのコンポーネントです。
翻訳先の変更は、DeepL APIで翻訳リクエストを行うためのtarget_langを切り替えることで実現します。
準備
音声出力する
まずは、前回のUnityProjectにTextToSpeech
コンポーネントをアタッチします。
今回はTranslateResult
ゲームオブジェクトにアタッチしました。
TextToSpeech
コンポーネントをアタッチすると、AudioSource
コンポーネントも一緒にアタッチされます。
TextToSpeech
には2つのオプションがInspector上から設定できます。
- Audio Source
使用するAudioSource
コンポーネントを設定する。 - Voice
音声ソース(しゃべるための音源)を変更する
TextToSpeech
コンポーネントのStartSpeaking(string)メソッドを使用することで、任意の文字列を音声出力することができます。
次に、音声出力有効/無効を切り替えるために、トグルボタンを配置します。
新しいトグルボタンをMRTK ToolBoxから選択し、シーン上に配置します。
今回は、アプリ起動時に音声出力を有効にしたいので、Interactable
コンポーネントのIsToggledを有効にします。
次に、翻訳結果を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); } } } }
Inspectorから対応するコンポーネントをアタッチすることで、翻訳結果取得時に、トグルボタンが有効な時には音声が出力されるようになりました。
翻訳先言語を変更する
これまでは英語にしか翻訳できなかったため、別言語にも翻訳できるようにします。
DeepL APIでは20種類以上の言語に翻訳することができます。
RadioButtons
オブジェクトをシーン上に配置し、InteractableToggleCollection
とGridObjectCollection
をアタッチします。
そのオブジェクトの子として任意の数(今回は4つ)のラジオボタンを配置し、InteractableToggleCollection
コンポーネントに登録します。
GridObjectCollection
では、ボタンを目的の並びになるようにパラメータを設定し、UnityEditor上からUpdate Collection
ボタンを用いて整列します。
参考:
次に、それぞれのボタンに言語情報を持たせるために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(); } } }
次に、現在ラジオボタンで有効になっている言語を翻訳時に取得するために、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
コンポーネントに参照させます。
これで、ラジオボタンを用いて、目的の言語に翻訳させる準備ができました。
動作確認
音声出力はアルファベットの出力の際しか取得できず、ドイツ語も発音が正しいかわかりませんが、英語では正しそうな音声出力結果を取得することができました。
中国語への翻訳の場合は、対応する文字をTextMeshProのフォントに登録していなかったため正しく表示されていません。今後対応する必要があります。
翻訳結果をTextToSpeechで音声出力するようにしてみた。
— napo tech (@SubNapo) October 31, 2021
出力がアルファベットの時しか音声出力されなさそうだし、ドイツ語は発音あってるかわからない。 pic.twitter.com/wwDThcv2Hs
これで、少なくとも日本語→英語への翻訳結果を音声出力することができました。