Hatena::Groupnadesiko

雪乃☆雫のなでしこ日和

2017/02/15 (水)

音声認識結果を抽出するよ!

| 15:09 | 音声認識結果を抽出するよ! - 雪乃☆雫のなでしこ日和 を含むブックマーク はてなブックマーク - 音声認識結果を抽出するよ! - 雪乃☆雫のなでしこ日和 音声認識結果を抽出するよ! - 雪乃☆雫のなでしこ日和 のブックマークコメント

 認識結果を切り出すのは、思ったよりは、簡単じゃ無かった(涙)

「クライアントがパーズしやすくするため, 1のメッセージ送信ごとに,データの終端として,"." のみの行が送信される.」

 ・・・て書いてあったから、そうなんだろうと、のつもりでやっていたら、どうもうまく出来ない

 おっかしいなあと思って、一受信ごと確認してみたら、他のタグは基本一行づつだからいいんだけど、複数行にわたる「<RECOGOUT></RECOGOUT>」タグは、どうも途中で結構途切れてた。

 送信時はそうでも、受信時には分割して受信してるってコトだろうね。

 しかも、一行づつとかゆう、分かりやすいブロックでは無くて、結構ヘンなところでバサッと分割されてしまうっぽい。

 認識結果が長いと分割されるというわけでも無いみたいで、わりと初っ端の文頭無音の辺りで一旦切れることが多いみたいなんだけど、位置は一定では無い。


 とりあえず、受信したモノの中に「<RECOGOUT>」があったら認識ブロックとしてログを取得し始めて、「</RECOGOUT>」があったら終了で、1ブロックの「<RECOGOUT></RECOGOUT>」タグを完成させてから、こからログを切り出すようにしてみたんだけど・・・

 もしも、「<RECOGOUT>」タグ自体が分断されたりすると、これもうまく働かないって話になってしまうけど・・・さすがにそれないかな? かな?

 取りあえず、のところはコレでうまくいってるような・・・???

# 認識結果を抽出。ログと比較。
#-----------------------------------------------------------
!「nakonet.nako」を取り込む。

#-----設定--------------------------------------------------
Julius起動バッチとは文字列=「run-win-gmm-module.bat」
接続待時とは整数=10
#-----宣言--------------------------------------------------
再試行とは整数=0
Jログとは文字列。
J認識結果とは文字列。
Jステータスとは文字列。
Jバージョンとは文字列。
認識ブロックとは文字列。

音声入力フラグ=オフ。
#-----------------------------------------------------------

#-----母艦設計----------------------------------------------
母艦のクライアント幅は1200。
母艦のクライアント高さは600。
母艦中央移動
オフ母艦の最大化ボタン有効変更。
母艦の閉じた時は~Julius終了
#-----------------------------------------------------------

#-----GUI------------------------------------------------
取得ログとはTエディタの幅は600。のレイアウトは「左」
音声認識とはTエディタの幅は600。のレイアウトは「右」

#---TCP-----
JクライアントとはTCPクライアント。
Jクライアントについて
  ホストは「127.0.0.1」  # 「127.0.0.1」はローカル。
  ポートは10500。  # モジュールモードではJuliusがサーバーとなり、ポート番号10500で接続を待ちます。
  接続した時は~
    再試行=接続待時。
    Julius接続完了時処理。
  受信した時は~
    Jクライアントで受信。
    それからJログ切り出し。
  エラー時は~
    Jクライアントで切断。
    もし、再試行<接続待時ならば、
      1秒待つ。再試行=再試行+1
      Julius接続。
    違えば、
      Jクライアントのエラーメッセージ言う。
      終わる。
#-----------------------------------------------------------
上バーとはパネル。
上バーについて
  レイアウトは「上」。高さは25。
  スタイルは「枠なし」。
  クリックした時は~
    「Julius情報」を「ステータス{~}バージョン{~}インスタンス情報{~}文法情報」でボタン選択。
    もしそれが「ステータス」ならば、Juliusステータス。
    違えばもしそれが「バージョン」ならば、Juliusバージョン。
    違えばもしそれが「インスタンス情報」ならば、Juliusインスタンス情報。
    違えばもしそれが「文法情報」ならば、Julius文法情報。

音声入力ボタンとは画像ボタン。
音声入力ボタンについて
  親部品は上バー。フラットはオン。テキストは「」
  位置は「0,0」。幅は150。高さは25。
  マウス入った時は~フラットはオフ。
  マウス出た時は~フラットはオン。
  クリックした時は~
    もし、音声入力フラグ=オフならば、音声入力中。
    違えば、音声入力開始待ち。

説明ラベルとはラベルの親部品は上バーの位置は「160,6」。
#-----------------------------------------------------------
音声入力開始待ち。
*音声入力開始待ち
  音声入力フラグ=オフ。
  Julius一時停止。
  音声入力ボタンの0,0をウィンドウ色塗る。
  文字色赤色文字サイズは14。
  音声入力ボタンの5,2へ「●」を文字描画。
  文字色黒色文字サイズは10。
  音声入力ボタンの30,5へ「音声入力開始」を文字表示。
  説明ラベルのテキストは「←ボタンを押すと音声認識を開始します。」

*音声入力中
  音声入力フラグ=オン。
  Julius再開。
  音声入力ボタンの0,0をウィンドウ色塗る。
  文字色青色文字サイズは14。
  音声入力ボタンの5,2へ「■」を文字描画。
  文字色黒色文字サイズは10。
  音声入力ボタンの30,5へ「音声入力停止」を文字表示。
  説明ラベルのテキストは「音声認識中・・・」
#-----------------------------------------------------------

#-----メイン------------------------------------------------
#バッチファイルを選択して起動。
「*.bat」のファイル選択して起動もしそれならば終わる。

#Julius起動バッチを起動。
//もし、Julius起動バッチの存在はいならば、Julius起動バッチを起動。
//違えば、「起動バッチがありません。」を言う終わる

//母艦最前面。
Julius接続。
#-----------------------------------------------------------

#-----Julius関数--------------------------------------------
●Julius起動(BATで)
  BATを起動。
  Julius接続。

●Julius接続
  Julius接続中処理
  Jクライアントで接続。

●Julius終了
  プロセス列挙反復
    対象を「julius」で正規表現マッチ。
    もしそれでなければ、対象プロセス強制終了。
#-----------------------------------------------------------
# エンジンを一時停止する.受信時点で入力待ちだったときは即座に停止する.
# 認識を実行中の場合,入力が終わり認識が終了してから停止する.
●Julius一時停止
  「PAUSE{\n}」をJクライアントで送信。

# エンジンを一時停止する.入力待ち・認識実行中にかかわらず,即時停止する.
●Julius即時停止
  「TERMINATE{\n}」をJクライアントで送信。

# 一時停止状態から復帰してエンジン動作を再開する
●Julius再開
  「RESUME{\n}」をJクライアントで送信。

# エンジンが現在動作中であるかどうかを返す
●Juliusステータス
  「STATUS{\n}」をJクライアントで送信。

# Julius のバージョンを返す
●Juliusバージョン
  「VERSION{\n}」をJクライアントで送信。

# すべての認識処理インスタンスの情報を出力する…いんすたんすってなんすか;
●Juliusインスタンス情報
  「LISTPROCESS{\n}」をJクライアントで送信。

# エンジンが現在持つ文法情報を返す
●Julius文法情報
  「GRAMINFO{\n}」をJクライアントで送信。
#-----------------------------------------------------------
●Jログ切り出し(Aから)
  Jログは「{Jログ}{A}」
  JステータスはAの「SYSINFO」から「PROCESS」をタグ属性取得。
  JバージョンはAの「ENGINEINFO」から「VERSION」をタグ属性取得。
  AでJuliusログ取得時処理。

  もし、Aを「<RECOGOUT>」で正規表現マッチでなければ、
    取得フラグ=オン。
  もし、取得フラグ=オンならば、
    認識ブロックは「{認識ブロック}{A}」
  もし、Aを「</RECOGOUT>」で正規表現マッチでなければ、
    取得フラグ=オフ。
    認識ブロックからJ認識結果抽出。
    認識ブロックは。

●J認識結果抽出({参照渡し 配列=?}Aから)
  No=0。J認識結果は。
  Aの要素数
    A\Noを「<WHYPO WORD=」で正規表現マッチ。
    もしそれでなければ、
      A\Noの「WHYPO」から「WORD」をタグ属性取得。
      もしそれが「<s>」またはそれが「</s>」ならばそれ。
      J認識結果は「{J認識結果}{それ}」
    No=No+1
  J認識結果はJ認識結果を改行区切る。
  J認識結果はJ認識結果を配列結合。
  J認識結果でJulius音声認識時処理。
#-----------------------------------------------------------
●Julius接続中処理
  取得ログは「{取得ログ}接続中...」。
  戻る。

●Julius接続完了時処理
  Julius即時停止。
  取得ログは「接続完了!{改行}音声入力を開始出来ます。{改行}」
  戻る。

●Juliusログ取得時処理(Aで)
  取得ログは「{取得ログ}{A}」。
  もし、Jステータス=でなければ、「STATUS:{Jステータス}」を言う。
  もし、Jバージョン=でなければ、「VERSION:{Jバージョン}」を言う。
  戻る。

●Julius音声認識時処理(Aで)
  音声認識は「{音声認識}{A}{改行}」。
  戻る。
#-----------------------------------------------------------

 あと、Juliusがクライアントから受け取れるメッセージを送れるようにしてみた。

 なんかよく分かんないから、引数の無いヤツだけ・・・

 欲しいのは、PAUSEとRESUMEだけだったけど、Juliusのバージョンが確認出来るっていうのも、ちょっといいよね。

 他のこともようく学べば、文法ファイルの追加や変更なんかが、再起動しなくてもクライアント側から操作できるような気がするので、後使えそうなんだけど・・・


 それと、プログラム終了とともに、Juliusも一緒に終了させたいんだけど、「DIE(Julius を強制終了する)」を送信するのは、確かに音声認識は強制終了されるっぽいんだけど、コマンドプロンプトの画面はもとより、タスクの中のJulius.exeものまま残ってしまっているから、意味ない感じなんだよね~。

 取りあえず、プロセス強制終了で終わらせちゃってるケド;


 他にひらめいた事としては、ぜんぜん関係ないけど、「ボタン選択」のダイアログって、ボタンが縦に並ぶ時と横に並ぶ時とあるんですよね~。

 こっちの意図に反して勝手に!

 一体なんなんだと思ってたけど、どうやら母艦?の幅に合わせて、横長すぎる場合は縦に並ぶよう、自動調整されてるっぽいですね。

 どうしても縦に並べたい! など見た目にこだわる場合には、やっぱり自前でフォームを用意するしかないんだろうね。

 どーでもいいことだけど、クイズの昔のナゾが解明したので、一応書いとく(爆)

うぇいくうぇいく2017/02/15 23:37TCPの世界では、ただのバイトの羅列なので、順序は(TCPなので)保障されますが、区切りという概念はありません。通信の開始から終了まで、連なります。

なので、受信したものを、だだーーっと、バッファ(文字列変数とか)にどんどん追加していって、自分のアプリケーションで処理を行えるというデータまでをため込んだら、その分を切り出して処理する という部分が必ず必要です。
ちゃんと切り出す前は、ただのバイト列のため、「文字コードに従って、1文字がばらけたりしない」ということもないです。そのため、使用する関数に注意が必要です。
(なでしこの文字列操作関数は、文字列がShiftJISじゃないとうまく処理できないものも結構あります)

雪乃☆雫雪乃☆雫2017/02/16 16:27 うぇいくさま、ありがとうございます☆
 なななんとー!><
 ・・・て、ふつうに日本語の状態でデータが飛び交っているわけないですもねー;
 よく考えたら、そりゃそうだというところなのですが、ばいとが・・・ばいなりが・・・なんて話は、頭がこんがらかってしまうのですよ;;;
 とっ、とにかく、全部取得してつながるまでは「<RECOGOUT>」タグどころの話ではなく、2バイト文字なんか化けてしまうかも知れないんですね。
 ああぁ~、ソレでピリオドだ!
 なんか今、ようやく意味が分かりました!!
 もっぺんやり直しです。
 ほんとうに、いつもありがとうございます!

トラックバック - http://nadesiko.g.hatena.ne.jp/snowdrops89/20170215