Unity Unityで音声認識 ~キーワードで取得~
あいさつ
どうも、はかせです。
ここ最近はずっとAlexaの開発をしておりました。
今までやったことのない分野でとても勉強になりました。
ただその中でAlexaに不満を持つことも多かったです。
ウェイクワードの件だったり、
前回のリマインダーの件だったり、
Alexaは何かと融通が利きません。
(おそらく誤動作と誤認識の軽減のため)
そうしていくうちにふとこう思いました。
「AlexaじゃなくてUnityで直接音声認識すればいんじゃね?」
もちろんAlexa×Unityというのが当初の技術的挑戦であり、
検証内容でした。
ただ目的が音声による操作ならばUnityで直接やってもいいはず。
ということで今回はUnityで直接音声認識をしてみる話です。
この記事では
Unityは2019.1.1f1、
マイクはノートパソコンの内臓マイクを使っています。
Unityで音声認識はできるのか
まず第一前提そういう機能やライブラリはあるのかって話です。
(ないならまた色々ごにょるだけですが・・・)
そして調べたらいっぱいありましたw
Alexaみたいにキーワード使うものから自由テキスト、
はては直接AudioCilpまで多種多様なものがありました。
Unityで直接提供されているものもあればWindowsの機能や
WebAPIだったりと叩き方もたくさんありました。
私が見たのは下記サイトですが、おそらく他にもあると思います。
qiita.com
さてこんだけあると何からやろうか迷いますね。
あくまでゲームの中で使いたいというとこなので
キーワードでやりましょう。
(迷って無くないか・・・?)
Unityでキーワードによる音声認識
キーワード認識はUnityが用意してくれている、
KeywordRecognizerというクラスを使えばできるみたいです。
docs.unity3d.com
ではまずさくっと使ってみましょう。
using UnityEngine; using UnityEngine.Windows.Speech; public class UnityVoiceTest : MonoBehaviour { public string[] mKeywords; private KeywordRecognizer mKeywordRecognizer; // Start is called before the first frame update void Start() { mKeywordRecognizer = new KeywordRecognizer(mKeywords); mKeywordRecognizer.OnPhraseRecognized += OnPhraseRecognized; mKeywordRecognizer.Start(); } private void OnDisable() { mKeywordRecognizer.Stop(); mKeywordRecognizer.Dispose(); } private void OnPhraseRecognized(PhraseRecognizedEventArgs args) { print(args.text); } }
このクラスの使い方は極めて単純です。
・キーワードの配列を用意する
・その配列をコンストラクタに渡しインスタンスを作る
・キーワードが発話された際に呼び出したい処理をイベントに追加する
・Startを呼び出し聞き取りを開始
・終わるときはDispose忘れずに
これだけです。
そして色々登録してみて色々話しかけてみました。
感想としては「内臓マイク使ってる割にはがんばってるな」です。
要はそこそこ精度いいです。
ただキーワードが発話の最初に無きゃ基本認識してくれません。
あとあんまり長いキーワードはうまく認識してくれないっぽい?
(私の滑舌悪い説濃厚)
なんかちょっと使い方めんどくさいな・・・
さっきのコードでは発話されたキーワードを
ただオウム返ししただけなのでそんなでしたけど、
キーワード毎にユニークな処理をしようと思うと地獄を見そうです。
というのも登録できるイベントハンドラーが一つしかないので
キーワードが増えれば増えるほど処理内で分岐が発生します。
private void OnPhraseRecognized(PhraseRecognizedEventArgs args) { switch(args.text) { case"a": break; case"b": break; case"c": break; case"d": break; //以下増えるだけ増える・・・ } }
いやああぁぁ!!!
こんなめんどくさいことは嫌なので
すこしでも楽にするためのオレオレラッパー作りました。
それがこちら
using System; using System.Linq; using System.Collections.Generic; using UnityEngine.Windows.Speech; public class MyKeywordRecognizer { private Dictionary<string, Action<string>> mKeyAndActionDic; private KeywordRecognizer mKeywordRecognizer; public MyKeywordRecognizer() { mKeyAndActionDic = new Dictionary<string, Action<string>>(); } ~MyKeywordRecognizer() { Dispose(); } /// <summary> /// キーワードの聞き取りを開始するタイミングで呼ぶ /// </summary> public void Start() { mKeywordRecognizer = new KeywordRecognizer(mKeyAndActionDic.Select(value => value.Key).ToArray()); mKeywordRecognizer.OnPhraseRecognized += OnPhraseRecognized; mKeywordRecognizer.Start(); } /// <summary> /// キーと対応する処理を登録する /// </summary> /// <param name="key">キー</param> /// <param name="action">処理</param> public void Add(string key, Action<string> action) { if (mKeyAndActionDic.ContainsKey(key)) throw new ArgumentException("キーが重複しています"); mKeyAndActionDic.Add(key, action); } /// <summary> /// 終了時に呼び出す /// </summary> private void Dispose() { if (mKeywordRecognizer.IsRunning) mKeywordRecognizer.Stop(); mKeywordRecognizer.Dispose(); } /// <summary> /// 受け取ったキーに対応する処理を呼び出す /// </summary> /// <param name="args"></param> private void OnPhraseRecognized(PhraseRecognizedEventArgs args) { if (!mKeyAndActionDic.ContainsKey(args.text)) return; mKeyAndActionDic[args.text](args.text); } }
やってることは単純でDictionaryを使って
キーワードと処理をペアで管理しています。
使い方がこちら
using UnityEngine; public class UnityVoiceTest : MonoBehaviour { private MyKeywordRecognizer mKeywordRecognizer; // Start is called before the first frame update void Start() { mKeywordRecognizer = new MyKeywordRecognizer(); mKeywordRecognizer.Add("アレクサ", text => print(text)); mKeywordRecognizer.Add("ボルテッカー", Borutekka); mKeywordRecognizer.Start(); } private void Borutekka(string text) { print("ピカチュウ!ボルテッカーだ!"); } }
Startの中でオレオレラッパーのインスタンスを作り
適時メソッドを呼び出して登録、聞き取りを開始しています。
KeywordRecgnizerインスタンスの管理は
ラッパーに任せているので使う側は気にしなくて問題ありません。
処理の登録はラムダでも普通のコールバックでもどちらもでも可です。
とにかく登録してスタートすればあとは良きに計らってくれます。
あとがき
今回はUnityの音声認識でした。
正直ゲームでAIに簡単な指示を出す程度ならば
全然問題なさそうでした。
(音声入力でチャットとかやろうとすると辛そうですが)
もしかしてUnity×Alexaを全然見かけなかったのは
このせいか・・・?
それでは今回はこの辺でノシ
ラッパーはGitHubに上げました。
github.com