なんちゃって音声認識サーバを作ろう
前の記事で音声認識を行う環境はできましたが、このままでは音声認識を使いたくなった場合に、その都度音声認識環境を構築しなければなりません。
それじゃああまりオシャレじゃないので、音声認識サーバを構築して各クライアントから利用できるようにします。
たったひとつの冴えたやりかた
音声認識サービスを構築するにあたって、いくつかの手段が考えられます。
- Juliusとは別にwebサービスを作成し、標準入出力等を利用してJuliusの機能を利用する。
- JuliusのAPIを組み込んだwebサービスを作成する。
- Juliusの入出力をネットワーク対応させる。
う~ん、どれもそれなりに面倒くさそう。
もう少し、何か手がないか考えてみよう。
終りなき戦い
Juliusのマニュアルを(今更ながら)熟読してみると、何やら興味深い記述に遭遇。
モジュールモード?何々。ネットワーク経由で音声認識結果を取得できます?
おおっ!正にお誂え向きの機能じゃないか!しかも動作確認のためのjcontrol.exeというツールまで用意されている。
説明を元にJuliusの起動バッチを作り、
.\bin\windows\julius.exe -C main.jconf -C am-gmm.jconf -demo -charconv utf-8 sjis -module
ついでにjcontrolの起動バッチも作って、
.\bin\windows\jcontrol.exe 127.0.0.1
ファイアウォールに穴もあけ、さーて準備OK。
両方のバッチを実行するとDOS窓が二つ開き、どうやら無事起動されたよう。
定番のセリフ「こんにちは」と話しかけると、xml形式で品詞とか発音情報とか信頼度スコアとかが表示されました。
<RECOGOUT>
<SHYPO RANK="1" SCORE="-2727.876221">
<WHYPO WORD="" CLASSID="<s>" PHONE="silB" CM="0.655"/>
<WHYPO WORD="こんにちは" CLASSID="こんにちは+感動詞" PHONE="k o N n i ch i w a" CM="0.424"/>
<WHYPO WORD="。" CLASSID="</s>" PHONE="silE" CM="1.000"/>
</SHYPO>
</RECOGOUT>
続けて「マイクテスト」としゃべったら、
<RECOGOUT>
<SHYPO RANK="1" SCORE="-2757.415039">
<WHYPO WORD="" CLASSID="<s>" PHONE="silB" CM="0.655"/>
<WHYPO WORD="バイク" CLASSID="バイク+名詞" PHONE="b a i k u" CM="0.097"/>
<WHYPO WORD="テスト" CLASSID="テスト+名詞" PHONE="t e s u t o" CM="0.120"/>
<WHYPO WORD="。" CLASSID="</s>" PHONE="silE" CM="1.000"/>
</SHYPO>
</RECOGOUT>
なるほど。単語ごとに結果が返されるのね(マイクがバイクとなったのはご愛敬)。
中々良いではないですか。では、本格的にクライアント機能を作ってみましょう。
(3分経過)
ところでプロトコルはどうなってるの?音声データはどうやって渡すの?
マニュアルを眺めてみたけどどうもよくわからない(実は重大な勘違いをしていたのですが、この時点では気づかず)。
せっかくのオープンソースですから、jcontrolのソースを見てみましょう。
う~ん。やっぱり音声データの受け渡しがされていないみたい。
(2時間ほど経過)
あっ!音声認識結果を取得できる!?
もしかして結果だけがネットワーク経由で受信できるってこと?
今一つ使い道がわかりませんが、どうやらそうゆうことのようです。
Oh my god!!! 振り出しにもどっちゃいました。
Juliusはそのままではサービス化できないのか?
やっぱり手ごろなクラウドサービスを使ったほうがいいのか?
自分で音声認識サービスを作ろうなどとは、見果てぬ夢だったのか?
あきらめきれずにマニュアルを眺めていると…「ふ~んプラグインも作れるのか」「音声入力プラグインなんてものも作れるのか」「うん?音声入力!」。
サービスということで無意識にhttp通信のようなものを考えていましたが、マイクがネットワーク越しにあるような入力モードさえあれば、とりあえず用は足せるはず。
あった。-input adinnet
これだ。
複数クライアントからの要求を捌いたりはできそうもないけど、当座はこれで凌げるはず。
あとは先ほどのモジュールモードを組み合わせれば、
Sotaで音声受信(お忘れかもしれませんが、そもそもの目的はコレ)
↓
音声認識サーバでテキスト化
↓
Sotaでテキストを元にした動作
うんうん、問題なさそう。
マイクで音声データを拾ってそれをネットワークに流す簡単なアプリを作って、先に作ったJulius起動バッチを少し直して、jcontrolのバッチも合わせて都合3つのバッチが完成。
因みに、Juliusはモジュールモードの場合だと先に結果通知先とのコネクションを作成するようなので、
- Julius起動
- jcontrol起動
- ネットマイク(仮名)起動
の順番で実行。この順番なら、途中でマイクを切って、その後再度マイクをコネクトすることができるはず。
なんでそんなことを考えるかって?
音声取得と音声認識後の応答(つまり発話)を同時に実行すると、Sotaが自分でしゃべったことを、また認識しようとするじゃないですか。
でも自分がしゃべる時はマイクを切っておけば(耳をふさぐ)、自分のコトバを聞かなくてすみます(音声データ受信後、直前の自分の発話データの逆位相のデータをかぶせてアクティブノイズキャンセラーとすればよいのですが、現時点では手が出ません)。
幼年期の終り
音声認識にかかわる仕組みは(とりあえず)できたっぽい。
これで、認識結果のテキストを手ごろな音声合成(例えばOpen JTalk)でそのまま発話すれば、オウム返しに会話をするはず(長くなるのでその件はまた今度)。
人間でいえば生後1~2歳の赤ちゃんにはなったはず。
次は、会話に応じてそれなりの応答を返す、もっと大人なシステムにしてみます(いつになるやら)。
以上、ten@蓼科情報でした。