はじめに
今回はOpenJTalk
を利用してテキストの音声読み上げをしてみるという記事になります。
といってもオリジナルのOpenJTalk
を使えるようにするのではなく、OpenJTalkForUnity
という簡単にUnityで利用できるようにしてくれたものが存在したのでそちらを利用させていただきます。
(補足に記述した理由より、後で自力でC#ラッパーを作成したいと思ってます)
環境
Unity2020.3.32f1
OpenJTalkForUnity v1.1.13
インストール
PackageManager
のAdd package from git URL....
にhttps://github.com/rarafy/OpenJTalkForUnity.git?path=_Project/Packages/OpenJTalkForUnity
と打ち込みます。
利用方法
利用しそうなコードを一覧にして記載しておきます。
private async void Start() { // 「こんにちは」と喋る OpenJTalk.Speak("こんにちは"); // ランダムな声で喋る OpenJTalk.SpeakRandomVoice("こんにちは"); // 指定したボイスで喋る OpenJTalk.Speak("こんにちは", "tohoku-f01-sad"); // 途中で話すのをやめる var ctx = new CancellationTokenSource(); _ = Task.Run(() => OpenJTalk.SpeakStoppable("こんにちは"), ctx.Token); await Task.Delay(TimeSpan.FromSeconds(1), ctx.Token); OpenJTalk.StopSpeaking(); // インストールされている全てのボイスをコンソールに出力する OpenJTalk.VoiceTypeInfo(); }
コードの中身について
最上位にいるクライアントクラスOpenJTalk
を載せておきます。
もっと細かく使いたい場合はJTalkTTS
を利用する形のようです。
github.com
public class OpenJTalk { // 参照------------------------------------------------------------------------------------------------------------------- private static JTalkTTS _tts = new JTalkTTS { VoiceName = "tohoku-f01-neutral" }; /// <summary> /// インストールされている全てのボイスの種類を表示します。<br/><br/> /// ※ボイスは"Assets\OpenJTalkForUnity\dll\voice"に格納されているものを探しに行きます。 /// </summary> public static void VoiceTypeInfo() { List<string> a = new List<string>(); a.AddRange(_tts.Voices.Select(v => v.Name).ToList<string>()); foreach (string item in a) Debug.Log(item); } // 発声(同期)------------------------------------------------------------------------------------------------------------------- /// <summary> /// ランダムな声で喋ります。引数にstringで喋らせたい文字列を与えてください。 /// </summary> /// <param name="text">喋らせたい文字列</param> /// <param name="speed">読み上げ速度</param> public static void SpeakRandomVoice(string text, double speed = 1.0) { using (JTalkTTS tts = new JTalkTTS { }) { tts.Voice = tts.Voices[new System.Random().Next(tts.Voices.Count)];//Voiceを設定 tts.Speed = speed;//読み上げ速度を設定 tts.SpeakAsync(text); tts.WaitUntilDone(); } } /// <summary> /// 任意のボイスで喋ります。引数に喋らせたい文字列とボイスの名前(tohoku-f01-neutral)を与えてください。<br /> /// 何も指定しない場合は"tohoku-f01-neutral"の声で「こんにちは」と話します<br /><br /> /// ※ボイスは"Assets\OpenJTalkForUnity\dll\voice"に格納されている必要があります。 /// </summary> /// <param name="text">喋らせたい文字列</param> /// <param name="VoiceName">ボイスの名前</param> /// <param name="speed">読み上げ速度</param> public static void Speak(string text = "こんにちは", string VoiceName = "tohoku-f01-neutral", double speed = 1.0) { using (JTalkTTS tts = new JTalkTTS { VoiceName = VoiceName }) { tts.Speed = speed;//読み上げ速度を設定 tts.SpeakAsync(text); tts.WaitUntilDone(); } } // 発声(非同期)------------------------------------------------------------------------------------------------------------------- private static JTalkTTS tts; private static CancellationTokenSource cancelToken; /// <summary> /// ランダムな声で喋ります。引数にstringで喋らせたい文字列を与えてください。 /// 特別な事情が無ければSpeakRandomVoice()よりもこちらを使うのが良いでしょう。 /// </summary> /// <param name="text">喋らせたい文字列</param> /// <param name="speed">読み上げ速度</param> public static Task SpeakRandomVoiceStoppable(string text = "こんにちは", double speed = 1.0) { tts = new JTalkTTS { }; tts.Voice = tts.Voices[new System.Random().Next(tts.Voices.Count)];//Voiceを設定 tts.Speed = speed;//読み上げ速度を設定 tts.SpeakAsync(text); cancelToken = new CancellationTokenSource(); while (tts.IsSpeaking) cancelToken.Token.ThrowIfCancellationRequested(); return null; } /// <summary> /// 何も指定しない場合は「こんにちは」と話します。<br/> /// 特別な事情が無ければSpeak()よりもこちらを使うのが良いでしょう。<br/><br/> /// ※ボイスはProjectの"Assets\OpenJTalkForUnity\dll\voice"に格納されていることが前提です /// </summary> /// <param name="text">喋らせたい文字列</param> /// <param name="VoiceName">ボイスの名前</param> /// <param name="speed">読み上げ速度</param> public static Task SpeakStoppable(string text = "こんにちは", string VoiceName = "tohoku-f01-neutral", double speed = 1.0) { tts = new JTalkTTS { VoiceName = VoiceName }; tts.Speed = speed;//読み上げ速度を設定 tts.SpeakAsync(text); cancelToken = new CancellationTokenSource(); while (tts.IsSpeaking) cancelToken.Token.ThrowIfCancellationRequested(); return null; } /// <summary> /// 発声を停止します。 /// </summary> public static void StopSpeaking() { if (cancelToken != null) cancelToken.Cancel(); if (tts.IsSpeaking) tts.Stop(); } }
OpenJTalkForUnity/OpenJTalk.cs at main · rarafy/OpenJTalkForUnity · GitHub
エラーが出てくる問題
どうやらアセンブリ周りでエラーが出力される問題があるようです。(私の場合は再起動したら出てこなくなりました)
ただ作者曰く、アンマネージドDLLの不具合で実使用に支障はないようです。
OpenJTalkForUnity/README_JP.md at main · rarafy/OpenJTalkForUnity · GitHub
またどうしても気になる場合は該当のファイルを削除してくださいとのことですが、manifest.json
(PackageManager
)経由だとファイルを削除できないんですよね・・・。
最悪.unitypackage
からインポートしなおして対応するのが良いでしょう。
補足
OpenJTalk For Unity
はWindows
のみ動作し、Mac
やUbuntu
では動作しないよというIssue
がありました。
Do you plan to make it work on Mac or Ubuntu? · Issue #3 · rarafy/OpenJTalkForUnity · GitHub
仮にもっと幅広いプラットフォームで動作させようと思ったら、ちゃんと自分でオリジナルのOpenJTalk
からC#ラッパーを作成する必要がありそうです。