音声認識してみよう

Julius(ジュリアス)のインストール

Juliusはラズパイでも使用可能なオープンソースの音声認識エンジンです。
オープンライセンスなので個人利用はもちろん、商用でも無償で利用することができます。

Juliusをインストールするシェルスクリプト「setup_julius.sh」を実行してください。

sh setup_julius.sh
#! /bin/bash
# setting up the Julius
# 音声認識エンジンJuliusのインストール

echo "Step0= setting snd-pcm-oss"
# for OSS
sudo apt-get -y install osspd-alsa
sudo sed -i -e 's/snd-pcm-oss//' /etc/modules
# for ALSA
sudo aptitude install libasound2-dev

echo "Step1= installing Julius"
cd
sudo sh -c "rm -r julius-master"
wget https://github.com/julius-speech/julius/archive/master.zip
unzip master.zip
rm master.zip
cd julius-master
./configure --with-mictype=alsa
make
sudo make install

echo "Step2= Getting and unzip Kits"
cd
sudo sh -c "rm -r julius-kit"
mkdir julius-kit
cd julius-kit
wget https://github.com/julius-speech/dictation-kit/archive/master.zip
unzip master.zip
rm master.zip
wget https://github.com/julius-speech/grammar-kit/archive/master.zip
unzip master.zip
rm master.zip
echo "finished"

Juliusをモジュールモードで起動する

音声認識をするために、まずはJuliusを「聞き耳状態」にする必要があります。Julius起動プログラム「boot_julius.sh」を実行してみましょう。

sh boot_julius.sh
#!/bin/bash
# Julius(キーワード認識版)をモジュールモードで起動
ALSADEV="plughw:1,0" julius -w data_julius.dic -C julius.jconf -module
exit 0

Juliusが起動する際、「julius.jconf」と「data_julius.dic」を読み込んでいるのがわかるでしょうか。「julius.jconf」は設定ファイルで、音声認識方法を細かく設定しているファイルです。

# Julius 設定ファイル:音声キーワード認識版
    -v /home/pi/julius-kit/dictation-kit-master/model/lang_m/bccwj.60k.htkdic          #単語辞書ファイル
    -h /home/pi/julius-kit/grammar-kit-master/model/phone_m/hmmdefs_ptm_gid.binhmm   # PTM triphone
-hlist /home/pi/julius-kit/grammar-kit-master/model/phone_m/logicalTri
-n 1                                      #n個の文仮説数が見つかるまで検索を行う
-output 1                                 #見つかったN-best候補のうち、結果として出力する個数
-input mic                                #マイクからの直接入力
-charconv euc-jp utf8                     #出力文字コードの変換(内部euc-jp, 出力utf-8)
-rejectshort 600                          #検出された入力の時間(msec)が閾値以下なら棄却
-lv 1500                                  #入力の振幅レベルのしきい値(0から32767の範囲。デフォルトは2000)

音声認識サンプルを実行する

先程まで使っていたLXTerminalはJuliusに専有されてしまっているので、新たなウィンドウを開きましょう。

Juliusの音声認識結果を受けて処理を行うためのサンプルプログラム「sample_julius1.py」を実行してみましょう。マイクに向かって「おはよう」「おはようございます」など朝の挨拶をしてみてください。べゼリーが「どうもです」と返事したら成功です。Ctrl+Cキーで終了します。

python3 sample_julius1.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Sample Code : julius音声認識サンプル

# モジュールのインポート
from time import sleep             # ウェイト処理
import subprocess                  # 外部プロセスを実行するモジュール
import socket                      # ソケット通信モジュール
import select                      # 待機モジュール
import sys                         # python終了sys.exit()のために必要

# 変数
ttsJpn = "exec_talkJpn.sh" # 音声合成
bufferSize = 256    # 受信するデータの最大バイト。2の倍数が望ましい。

# 関数
def socket_buffer_clear():
  while True:
    rlist, _, _ = select.select([client], [], [], 1)
    if len(rlist) > 0: 
      dummy_buffer = client.recv(bufferSize)
    else:
      break

# TCPクライアントを作成しJuliusサーバーに接続する
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
enabled_julius = False
for count in range(3):
  try:
    client.connect(('localhost', 10500))
    # client.connect(('10.0.0.1', 10500))  # Juliusサーバーに接続
    enabled_julius = True
    break
  except socket.error:
    print ('failed socket connect. retry')
    pass
if enabled_julius == False:
  print ('Could not find Julius')
  sys.exit(1)

# メインループ
new = ""
try:
  print ('音声認識開始')
  cmds = ['sh',ttsJpn, 'こんにちは'] # コマンドリストの作成
  proc = subprocess.Popen(cmds, stdout=subprocess.PIPE) # コマンドの呼び出し
  proc.communicate() # コマンド実行プロセスが終了するまで待機
  data = ""
  socket_buffer_clear()
  while True:
    data = str(client.recv(bufferSize)).decode('utf-8')  # Juliusサーバーから受信
    if "<RECOGOUT>" in data:
      new = ""
    new = new + data
    if "</RECOGOUT>" in new:  # RECOGOUTツリーの最終行を見つけたら以下の処理を行う
      print (new)
      if u"朝の挨拶" in new:
        cmds = ['sh',ttsJpn, 'どうもです'] #
        proc = subprocess.Popen(cmds, stdout=subprocess.PIPE) # コマンドの呼び出し
        proc.communicate() # コマンド実行プロセスが終了するまで待機
      else:
        print ("not mached")
      socket_buffer_clear()
      new = ""

except KeyboardInterrupt: # CTRL+Cで終了
  client.close()
  sys.exit(0)

「RECOGOUTってなんやねん?」と思ったかもしれませんね。Juliusは音声認識結果を、以下のような感じでpythonに送ってきます。<RECOGOUT>タグと</RECOGOUT>タグに囲まれた部分が音声認識された結果なのです。

<INPUTPARAM FRAMES="98" MSEC="980"/>
.
<RECOGOUT>
  <SHYPO RANK="1" SCORE="-2356.354980" GRAM="0">
    <WHYPO WORD="朝の挨拶" CLASSID="朝の挨拶" PHONE="silB o h a y o u silE" CM="0.997"/>
  </SHYPO>
</RECOGOUT>
.

好きな言葉に反応できるようにする

先程の例では何種類かの「朝の挨拶」にしか反応しませんでしたが、データを追加することで反応するキーワードを増やすことができます。最終的なJulius向けのデータは拡張子が「.dic」になりますが、まずは以下のようなcsvファイルを作ることから始めます。分類とキーワードをカンマで区切って書いていくだけです。

cat data_julius.cvs

朝の挨拶,おはよう
朝の挨拶,おっは
朝の挨拶,おはようございます
朝の挨拶,もーにんぐ
昼の挨拶,こんにちは
昼の挨拶,こんちはー
昼の挨拶,ちわー
昼の挨拶,おっす
昼の挨拶,はろー
昼の挨拶,よお
昼の挨拶,へいっ
夜の挨拶,こんばんわ
テスト,てすとです
テスト,てすと
テスト,きこえますか
テスト,ちぇっく
テスト,きこえてる

上記のcvsファイルをtool_julius.shによってJulius用の辞書ファイルdata_julius.dicに変換することで、Julius起動時に読み込まれ、キーワード認識ができるようになります。

sh tool_julius.sh
#!/bin/bash
# csvデータをtsvに変換
sudo sed -E "s/,/    /g" data_julius.csv > data_julius.tsv
# tsvファイルをjuliusのdic形式に変換
sudo iconv -f utf8 -t eucjp data_julius.tsv | ./tool_yomi2voca.pl > data_julius.dic
exit 0

「tool_yomi2voca.pl」というのはJuliusが提供している辞書データ作成ツールです。
以上です。これで好きなキーワードにべゼリーを反応させることができるようになりました。if文を追加していくことで、どんどん複雑な会話ができるようになります。