Unity から iOS の Speech で音声認識する


iOS10 で公開された Speech API ですが、もう iOS11 も出たという今頃になって、 Unity から使ってみたくなりました。
しかし plugin はどうやら誰も公開していなかったようなので、作ってみました。

TL;DR

GitHub で公開していますので、 clone して使ってください。
https://github.com/noir-neo/UniSpeech

使い方

ISpeechRecognizer を実装する

public class SpeechRecognizer : MonoBehaviour, ISpeechRecognizer
{
    // 音声認識したときに呼ばれる
    public void OnRecognized(string transcription) { }

    // アクセスが承認されたときに呼ばれる
    public void OnAuthorized() { }

    public void OnError(string description) { }
    public void OnUnauthorized() { }
    public void OnAvailable() { }
    public void OnUnavailable() { }
}

コールバックを受け取る GameObject の名前を登録する

UniSpeech.SpeechRecognizer.CallbackGameObjectName = gameObject.name;
サンプルプロジェクトでは Start() に書いています。

ユーザーに音声認識へのアクセスの承認を求める

UniSpeech.SpeechRecognizer.RequestRecognizerAuthorization();
同じくサンプルプロジェクトでは Start() に書いています。

音声認識を開始する

UniSpeech.SpeechRecognizer.StartRecord();
サンプルプロジェクトでは OnAuthorized() に書いています。

実装の説明

Swift での SpeechRecognizer の実装

ほぼ Apple のサンプルコードのままなので特筆すべきことはないです。

Unity -> Swift のブリッジ

上記のサンプルが Swift だったり、情報量が逆転してきていて Swift で書きたかったので、こちらの plugin を使いました。
https://github.com/miyabi/unity-swift

これを入れればほとんどいい感じになるのですが、 objective-c での interface の定義だけは必要なので、3重定義になってしまうのはなんとか自動生成にしたいと思いました。

さいごに

さすがに認識精度はかなり高いです。
Unity からモバイルで使える音声認識というと、まだ何かとハードルが高いのが現状ですが、マルチプラットフォームを捨ててサクッとネイティブの機能を使うという選択肢も用意してみました。

Android も同じように音声認識の API が公開されているので、インタフェースを揃えたプラグインにしたら便利そうだなとは思いましたが、特にやる予定はありません。

また native -> Unity に string 以外を返そうとすると面倒なので今回は端折りましたが、 bestTranscription 以外も返すようにするとか、使い勝手の改善の余地はあって、それは気が向いたらやっていきます。