はじめに
今回はWebGLで音声認識をしてみる記事になります!
Unityで音声認識をしようと思うと、Unityの標準のものやJulius
,Google Cloud Speech API
などがあります。
しかし、ブラウザ上で動かすとなると様々な制限があるので私が調べた範囲では、Web Speech API
一択なような気がしました。
そこでUnityでWeb Speech API
を使った記事を見たところ、WebSocketSharp
というライブラリを用いて通信をするものがほとんどです。
ぶっちゃけたところWebSocketについてはミジンコ並の知識すら持っていないので、ぐぬぬ・・・と思っていたところ、公式にこんなページがあることを見つけました。
このページの冒頭を引用させてもらうと、
Web 用のコンテンツを構築するときは、Web ページ上の他の要素とやり取りする必要があります。また、Web API を使用して Unity が現在デフォルトで公開していない機能を実装したい場合もあるかもしれません。 いずれの場合も、ブラウザーの JavaScript エンジンと直接やり取りする必要があります。Unity WebGL はこれを行うためのさまざまな方法を提供します。
とのことで、これを使えばWebSocketSharp
すら使う必要ないんじゃね?っということで実際にやってみました!
追記)サンプルを公開してみました。是非体験してみてね。
https://hanachiru.github.io/WebSpeeshAPITest2/
※WebSpeechAPIはChromeのみ対応です
自作WebGLテンプレートを作成する
まずは以下の公式サイトにもあるように、WebGLテンプレートを作成します。
WebGLテンプレートはEdit -> ProjectSettings -> Player
から見れるやつのことですね。
Assets/WebGLTemplates/テンプレート名/
にindex.html
を作成します。私はテンプレート名をCustom
にしました。
このindex.html
に必要最低限のHTMLソースを書きます。
<!DOCTYPE html> <html lang="en-us"> <head> <meta charset="utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Unity WebGL Player | %UNITY_WEB_NAME%</title> <script src="%UNITY_WEBGL_LOADER_URL%"></script> <script> var gameInstance = UnityLoader.instantiate("gameContainer", "%UNITY_WEBGL_BUILD_URL%"); </script> </head> <body> <div id="gameContainer" style="width: %UNITY_WIDTH%px; height: %UNITY_HEIGHT%px; margin: auto"></div> </body> </html>
あと自分のテンプレートを選択しておくのを忘れないでおきましょう。
Chromeで試してみる
まずはUnityで使うためのJavascript
のコードが動くかChromeで試してみましょう。
<script> function Start(){ SpeechRecognition = webkitSpeechRecognition || SpeechRecognition; const recognition = new SpeechRecognition(); recognition.continuous = true; recognition.onnomatch = function(){ window.alert("ページの再読み込みをしてください。") }; recognition.onerror = function(){ window.alert("エラーが発生しました。再接続をします。") Start(); }; recognition.onsoundend = function(){ window.alert("音声入力が停止しました。再接続します。") Start(); } recognition.onresult = (event) => { window.alert(event.results[event.results.length - 1][0].transcript); }; recognition.start(); } Start(); </script>
Web Speech API
を使った簡単なHTMLコードを書いてみました。
是非これをローカルサーバーで実行してみてください。
JacaScriptからUnityのメソッドを呼び出す
次にJavaScriptからUnityのメソッドを呼び出してみましょう。
これをするためには以下のコードを使います。
SendMessage(objectName, methodName, value);
引数 | 意味 |
---|---|
objectName | シーンのオブジェクトの名 |
methodName | 現在オブジェクトにアタッチされているスクリプトのメソッド名 |
value | 文字列、数字など |
これと先程のJavaScriptのコードをWebGLテンプレート(index.html)に合体させてみました。
<!DOCTYPE html> <html lang="en-us"> <head> <meta charset="utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Unity WebGL Player | %UNITY_WEB_NAME%</title> <script src="%UNITY_WEBGL_LOADER_URL%"></script> <script> var gameInstance = UnityLoader.instantiate("gameContainer", "%UNITY_WEBGL_BUILD_URL%"); function Start() { SpeechRecognition = webkitSpeechRecognition || SpeechRecognition; const recognition = new SpeechRecognition(); recognition.continuous = true; recognition.onnomatch = function () { window.alert("セットアップに失敗しました。ページの再読み込みをしてください。") }; recognition.onerror = function () { console.log("エラーが発生しました。再接続をします。") Start(); }; recognition.onsoundend = function () { console.log("音声入力が停止しました。再接続します。") Start(); } recognition.onresult = (event) => { gameInstance.SendMessage('GameManager', 'OnMessage', event.results[event.results.length - 1][0].transcript); }; recognition.start(); } Start(); </script> </head> <body> <div id="gameContainer" style="width: %UNITY_WIDTH%px; height: %UNITY_HEIGHT%px; margin: auto"></div> </body> </html>
JavaScriptコードを Unity から呼び出す方法もあるのですが、どうせずっと実行している必要があるのでその方法はとりませんでした。
というか実際にやってみたらうまく動かなかったんですよね・・・。HelloWorld的な奴は動いたのでコードがダメだったんだとは思いますが。
UnityでC#のスクリプトを書く
最後にゲームオブジェクトにアタッチするコードを書きます。
using UnityEngine; using UnityEngine.UI; public class Sample : MonoBehaviour { [SerializeField] private Text _text; public void OnMessage(string message) { Debug.Log("Recieved a message"); _text.text = message; } }
もはやこれは説明不要ですね。
忘れずにゲームオブジェクトにアタッチして任意のテキストの参照をインスペクターから設定しましょう。
またゲームオブジェクトの名前はSendMessage
に対応しなければならないので、今回の場合はGameManager
です。
試してみる
最後にプロジェクトをWebGLでビルドしましょう。
すると最初に貼ったGIFのような動きをすると思います。
さいごに
この方法ならWebSocketSharp
を使わずに簡単に音声認識ができました。
実際に使ってみた感じ音声認識の精度は抜群に良いと思います。
ただ私自身理解が及んでいないことがたくさんあるので、なにか追記やこうした方がいいんじゃない?といったご意見をコメント等にいただけると嬉しいです。
またこちらの記事はUnityとJavaScriptの連携をとても簡潔にまとめてくださっていてよかったら見てみてください。
UnityのWebGLで外部JavaScriptライブラリを使う - Qiita
追記)いくつか改善をしたところをまとめてみました。こちらも是非。
【Unity】WebGLでなるべく簡単に音声認識をしてみた② - はなちるのマイノート