トップ > 【Unity】Juliusでリアルタイム音声認識する方法を紹介します!
更新日 2023/3/5

【Unity】Juliusでリアルタイム音声認識する方法を紹介します!

Juliusは商用利用可能なオープンソースの音声認識エンジンです。今回はUnityでJuliusを利用してマイクで話した言葉をリアルタイムでテキストに変換する方法についてまとめます。

大語彙連続音声認識エンジン Julius https://julius.osdn.jp/

Juliusを利用するための準備

Juliusは簡易的に使えるように音声認識パッケージを配布しています。今回はディクテーションキット(自動口述筆記)を利用して音声認識をしたいと思います。最初にディクテーションキット version 4.5をダウンロードして解凍して下さい。

Julius音声認識パッケージ https://julius.osdn.jp/index.php?q=dictation-kit.html

dictation-kit-4.5/run-win-gmm.batを実行して「こんにちは」と話しかけて音声認識されるか確認して下さい。

Julius_Demo

プログラムから利用するためにモジュールモードで起動できるようにします。dictation-kit-4.5/run-win-gmm.batを開いてオプションを書き換えます。

.\bin\windows\julius.exe -C main.jconf -C am-gmm.jconf -demo -charconv utf-8 sjis

-demoと-charconvオプションを削除して-moduleオプションを追加します。

.\bin\windows\julius.exe -C main.jconf -C am-gmm.jconf -module

実行してモジュールモードでの起動を確認して下さい。

Julius_Module

Module mode readyと表示されればモジュールモードで起動しています。


Juliusを利用したコーディング

Juliusをモジュールモードで起動しするとローカルホストにサーバーが立ち上がります。Socketを利用して127.0.0.1のポート番号10500へ接続します。

Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

await socket.ConnectAsync("127.0.0.1", 10500);

ループしてJuliusサーバーからのレスポンスを待ちます。レスポンスはXML形式のUTF8のバイト配列で送られてくるのでEncoding.UTF8.GetStringを利用して文字列化しています。

byte[] buffer = new byte[1024];
ArraySegment<byte> segment = new ArraySegment<byte>(buffer, 0, buffer.Length);
while (true)
{
int byteReceived = await socket.ReceiveAsync(segment, SocketFlags.None);
string xml = Encoding.UTF8.GetString(buffer, 0, byteReceived);
}

XMLは以下のような形式で送られてきます。

<RECOGOUT>
<SHYPO RANK="1" SCORE="-4150.723145">
<WHYPO WORD="" CLASSID="<s>" PHONE="silB" CM="0.745"/>
<WHYPO WORD="おはよう" CLASSID="おはよう+感動詞" PHONE="o h a y o:" CM="0.809"/>
<WHYPO WORD="ござい" CLASSID="ござい+動詞" PHONE="g o z a i" CM="0.928"/>
<WHYPO WORD="ます" CLASSID="ます+助動詞" PHONE="m a s u" CM="0.861"/>
<WHYPO WORD="。" CLASSID="</s>" PHONE="silE" CM="1.000"/>
</SHYPO>
</RECOGOUT>

本来ならXMLパーサーを使うべきですが、今回は処理を簡単にするためにWORD属性の文字列を連結して</RECOGOUT>で文章の終了とします。Regexを利用して正規表現でWORD属性の文字列を取得します。

Match match = Regex.Match(str, "WORD=\"([^\"]*)\"");
if(match.Success)
{
message += match.Value[6..(match.Value.Length - 1)];
}

プログラムを終了するときに接続を閉じます。

socket.Shutdown(SocketShutdown.Both);
socket.Close();

全ソースコード JuliusTest.cs

using System;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using UnityEngine;

public class JuliusTest : MonoBehaviour
{
Socket socket = null;

void Start()
{
Task.Run(() => Connect());
}

void OnDisable()
{
if(socket != null)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}

async void Connect()
{
socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

await socket.ConnectAsync("127.0.0.1", 10500);

byte[] buffer = new byte[1024];
ArraySegment<byte> segment = new ArraySegment<byte>(buffer, 0, buffer.Length);
string message = "";

while (true)
{
int byteReceived = await socket.ReceiveAsync(segment, SocketFlags.None);
string xml = Encoding.UTF8.GetString(buffer, 0, byteReceived);
string[] strs = xml.Split('\n');
foreach (var str in strs)
{
Match match = Regex.Match(str, "WORD=\"([^\"]*)\"");
if(match.Success)
{
message += match.Value[6..(match.Value.Length - 1)];
}
else if(str.Contains("</RECOGOUT>"))
{
Debug.Log(message);
message = "";
}
}
}
}
}

確認用シーンの作成と実行

確認用のUnityシーンを作成します。ヒエラルキーで適当なゲームオブジェクトを作成しインスペクターでJuliusTest.csを追加します。

Julius_Scene

Juliusをモジュールモードで起動した後でUnityを実行します。

Julius_Run

喋った言葉がログ表示されることを確認して下さい。


マイクからの音声をテキストに変換することができました。
字幕やコミュニケーションツールなどに使えそうですね。


関連ページ


Copyright ©2022 - 2024 うにぉらぼ