テキスト読み上げ機能の実装【Unity】【EasyTTS】

テキスト読み上げ機能

開発中のアプリに英単語の発音機能を実装したくて、EasyTTS(有料Asset 5ドル)を使って見た話。

これさえいれておけばAndroidでもiOSでもテキストを読み上げてくれる。ツール系のアプリにも使えそう。

Easy TTS

要求スペック

iOS7 以上
Adroid 1.6以上
AndroidではTTS Engineがインストールされている必要あり。

実装方法

需要が少ないのか、情報が少なかった。

公式が参考になるかな。

使い方はとても簡単。

①EasyTTSのパッケージをインポート

②使用するメソッドは以下
EasyTTSUtil.SpeechAdd (a string that converts into speech)
EasyTTSUtil.Initialize()
EasyTTSUtil.Stop()

 公式に下記デモコードあり。

DemoEasyTTS.cs

public class DemoEasyTTS : MonoBehaviour {
 
    private string stringToEdit = "Test";
 
    void OnGUI ()
    {
        stringToEdit = GUI.TextField (new Rect (Screen.width/2-100, Screen.height/2-100, 200, 50), stringToEdit,200);
        if (GUI.Button (new Rect (Screen.width/2-50, Screen.height/2-20, 100, 40), "Speak")) {
 
            EasyTTSUtil.SpeechAdd(stringToEdit);
        }
    }
 
    void Start(){
        EasyTTSUtil.Initialize (EasyTTSUtil.UnitedStates);
    }
   
    void OnApplicationQuit()
    {
        EasyTTSUtil.Stop ();
    }
}

Start時にEasyTTSUtil.Initialize(EasyTTSUtil.UnitedStates)で使用する言語を指定して初期化。

EasyTTSUtil.Speech (a string that converts into speech) で読み上げたいTextを引数に渡す。

読むのを止めたいときは

EasyTTSUtil.Stop()を呼ぶ。

※Android, iOSの違いを意識する必要はない。

簡単!と思いきや。。

iOS実機でデバッグすると、EasyTTS.Speech(string)を呼んだときに1フレーム内で処理しきれず、かくついてしまう。。

これじゃ使い物にならないよ。。。。ということで。

EasyTTSのコード内部を調査

EasyTTS.mm

static EasyTTSUtil *tts = nil;

void EasyTTSUtilSpeech(char* text,char* _local)

{

if(tts == nil)

{

tts = [EasyTTSUtil alloc];

}

NSString *sName = (text != nil) ? [NSString stringWithUTF8String: text] : [NSString stringWithUTF8String: ""];

NSString *slocal = (text != nil) ? [NSString stringWithUTF8String: _local] : [NSString stringWithUTF8String: ""];

[tts convertTextToSpeech:sName local:slocal];

}

出たよ。。objective-c。。。nilって気持ち悪い。。

よくわからないけど、解読すると、EasyTTSUtil.Speechを最初に呼び出したときにttsがnil(null?)のとき、memory allocしてるっぽい。メモリの確保は結構重い処理だろうから、ここがボトルネックかな?ということで下の関数を切り出し。

void EasyTTSUtilAlloc()
{
   if(tts == nil)
   {

     tts = [EasyTTSUtil alloc];

   }
}

EasyTTSUtil.cs

public class EasyTTSUtil
{
	#if UNITY_IPHONE && !UNITY_EDITOR
	[DllImport("__Internal")]
	private static extern void  EasyTTSUtilSpeech(string text,string local);
	[DllImport("__Internal")]
	private static extern void EasyTTSUtilStop();
	[DllImport("__Internal") // →追記
	private static extern void EasyTTSUtilAlloc(); //→追記
        //以下省略...
}

EasyTTSUtilAlloc()はobjective-cコードのため、c#コードでよびだせるよう、2行分追記。

EasyTTSUtil.cs/Initialize


	public static void Initialize(string local = UnitedStates,string enginePkg = null)
	{
		#if UNITY_ANDROID && !UNITY_EDITOR
		//省略
		}
		#elif UNITY_IPHONE && !UNITY_EDITOR
		localSetting = local;
		EasyTTSUtilAlloc(); //追記
		#endif
	}

EasyTTSUtil.csのScriptで初期化時にメモリ確保するように変更。

EasyTTSUtil.cs内コードInitializeメソッド内にEasyTTSUtilAlloc()を追記。

EasyTTS.Initialize()を呼んだときに、メモリを確保しておく。
あとは通常の使い方の通り、使う前にInitializeを呼んで、EasyTTSUtil.Speech(string)を実行するだけ。

ちゃんと評価できてないけど、Unity Profilerで確認したら、スパイクが小さくなったし、フレーム遅延もなくなってそうだから、良しとしよう。

※iOS版は改善されたけど、Android版は確認できてない。。

いろいろと試行錯誤したけど、英単語ひとつひとつの音声ファイル用意するよりは簡単かな。

Twitterでご教示いただいた方々ありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA