AndroidでマルチリンガルTTS(音声合成)アプリ

9月に入社しました、Androidアプリ開発者のたかなです。
今日はAndroidの搭載機能である「TTS(音声合成)」を用いた マルチリンガルTTSアプリを作ってみたいと思います!

TTSとは
TTSは Text To Speech の略です。読んで字のごとく、音声合成を指します。
初音ミクなどのVocaloid、駅のアナウンス、ロボットに搭載されている音声を耳にしたことがある人も多いでしょう。棒読みちゃんを使っている人もいるかもしれませんね。
TTSは「動的に変化する情報をリアルタイムにしゃべってほしい」「状況に応じて素早くアナウンスしたい」「いつでも、どこでも、手間をかけずに情報を発信したい」といったニーズに対応するよう作られ、郵便局や病院の番号札の読み上げなどから、近年では肉声に近いなめらかな発音のモデルも増えてきました。
AndroidにTTSが標準搭載
Android 1.6から、TTS機能が標準搭載されています。
ただし、音声を合成するためにはボイスデータと呼ばれる音声のパーツの集合(アプリ形式)をインストールする必要があり、そのままでは使うことができません。
今回のアプリではその点を加味して、ボイスデータの有無をチェック、なければマーケットの該当アプリへ遷移する、という機能も付加しています。
AndroidTTSの対応言語
現在、AndroidTTSの対応言語は「英語(イギリス英語を含む)」「フランス語」「ドイツ語」「イタリア語」「スペイン語」の5つです。 自分のAndroid端末がどの言語をしゃべれるかは、「設定」→「音声入出力」→「テキスト読み上げの設定」→「言語」で確認できます。
残念ながら日本語非対応とのことで、日本語の合成を実現するためには別のライブラリが必要です。
AndroidTTSを使ってみる
SDKの「TextToSpeech」クラスを使います。
リファレンスはこちら TextToSpeech - Android Developers
しゃべらせること自体はとても簡単で、 speakメソッドの引数に読んでほしいテキストを与えるだけです。
各言語の設定を行うにはsetLanguageメソッドでLocaleを指定します。
今の設定がどの言語か?を調べるためにはgetLanguage()しましょう。
また、自分以外の人の端末でアプリを使って欲しい場合は、その端末の対応言語を調べる必要があります。
これはisLanguageAvailableメソッドにLocaleを指定することで、ステータスがTextToSpeechの定数として返ってきます。
例)端末がアメリカ英語のTTSに対応可能かを判断するためには
if (mtts.isLanguageAvailable(Locale.US) >= TextToSpeech.LANG_AVAILABLE) { //対応可能だった時の処理 }
となります。 TextToSpeech.LANG_AVAILABLEは「言語が使用可能である」ことを指していて、 ステータスがLANG_AVAILABLE以上の状態であれば合成が可能です。
余談ですが、サポートされていないLocaleならLANG_NOT_SUPPORTED、必要なボイスデータがインストールされていないとLANG_MISSING_DATAが返ってくるので、必要に応じて処理を加えましょう。
作ってみよう
アプリの仕様です。
- はじめにボイスデータがあるかどうかチェックする
- ヘルプボタンを押すとガイド音声が流れる
- デフォルトはアメリカ英語
- テキストを入力して「TextToSpeech!」ボタンを押すと合成し再生
- 「Laguage」ボタンで言語の切り替えが可能
サンプルコード
TextToSpeechActivity.java
package jp.android; import java.util.Locale; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.speech.tts.TextToSpeech; import android.view.View; import android.widget.Button; import android.widget.EditText; public class TextToSpeechActivity extends Activity implements TextToSpeech.OnInitListener { private static final int CHECK_TTS = 682730935; private Button mSpeakButton; private TextToSpeech mTts; private EditText et; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.checkTTS(); mTts = new TextToSpeech(this, this); this.mSpeakButton = (Button) findViewById(R.id.speak_button); et = (EditText)findViewById(R.id.inputText); mSpeakButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { startTTS(et.getText().toString()); } }); } /** * TTSエンジンがインストール済かどうかを判定 */ private void checkTTS() { Intent intent = new Intent(); intent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA); startActivityForResult(intent, CHECK_TTS); } // チェックの結果を受け取る protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CHECK_TTS) { if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) { //インストール済ならウェルカムメッセージを発話 startTTS("Welcome to TTS application, Let`s start!"); } else { //インストール無しなら Intent install = new Intent(); install.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA); startActivity(install); } } } /** * 合成を実行 * @param text 読み上げたいテキスト */ private void startTTS(String text) { mTts.speak(text, TextToSpeech.QUEUE_FLUSH, null); } /** * ヘルプガイドを読み上げる * @param v */ public void startGuide(View v) { mTts.setLanguage(Locale.US); startTTS(getString(R.string.guide)); } /** * 言語選択ボタン * @param v */ public void onSelectLang(View v) { AlertDialog.Builder ab = new AlertDialog.Builder(this); String[] str = {"English","French","German","Italian","United Kingdom"}; ab.setItems(str, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int i) { switch (i){ case 0: mTts.setLanguage(Locale.US); break; case 1: mTts.setLanguage(Locale.FRENCH); break; case 2: mTts.setLanguage(Locale.GERMAN); break; case 3: mTts.setLanguage(Locale.ITALIAN); break; case 4: mTts.setLanguage(Locale.UK); break; } } }); ab.show(); } public void onInit(int status) { if (status == TextToSpeech.SUCCESS) { if (mTts.isLanguageAvailable(Locale.US) >= TextToSpeech.LANG_AVAILABLE) { //アメリカ英語に設定 mTts.setLanguage(Locale.US); } } } @Override protected void onDestroy() { super.onDestroy(); mTts.shutdown(); } }

非常に簡単にマルチリンガルなTTSアプリが作れました。
注意点
speakメソッドは非同期なので、音声の合成処理・再生中はタスクの状態に応じた処理が必要です。特に長い文章を読ませたい場合(入力される文字数を制限しない場合)は注意しましょう。
サンプルプロジェクトのソース
スペースの関係で全部のソースは載せられないので、こちらに置いておきます。
https://www.assembla.com/code/texttospeech/git/nodes
まとめ
AndroidTTSを使うと、手軽に音読アプリが作れます。
合成から音声再生までのレスポンスが速いので、ちょっとした外国語のトレーニングに使えそうですね。
定型文をあらかじめ入力しておけば、海外旅行にも役立ちそうです。
また、今年1月から、全てのAndroid端末で 音声対話型コンシェルジュサービスnetpeople : aが利用可能になるとのことなので、TTSが日本語サポートされたら端末同士の会話が実現するかもしれません。
<おまけ>Androidで使える日本語TTSライブラリ
日本語で音声合成してみたい!という方向けに公開されているライブラリです。
有料のものがほとんどなので、気軽に試せないのが少し残念ですね。
音声合成エンジン "Galatea Talk"を用いたライブラリ
- Android JaTTS
- AquesTalk
- ドキュメントトーカ日本語音声合成エンジン for Android
- VoiceText
- micro AITalk
株式会社アクエストの音声合成ライブラリ。評価版あり。
クリエートシステム開発株式会社の音声合成ライブラリ。Android用SDKになっています。
HOYA株式会社の音声合成ライブラリ。中国語・韓国語に対応しているよう。
株式会社エーアイの音声合成ライブラリ