Python

ラズパイで音声認識(Juliusインストールからソケット通信まで解説)

スポンサーリンク

本記事では、音声認識エンジンJuliusのインストールからPythonを使って動かすところまで詳しく解説します!使用するJuliusのバージョンは4.5です。

他の方々のサイトを参考にしながら行ったのですが、4.5でやっている方がいなかったので実装してみました。その際、つまづいた点などもありましたので詳しくお伝えしますね。

Juliusとは

Julius は,音声認識システムの開発・研究のためのオープンソースの高性能な汎用大語彙連続音声認識エンジンです. 数万語彙の連続音声認識を一般のPCやスマートフォン上でほぼ実時間で実行できる軽量さとコンパクトさを持っています.(Julius公式サイトより)

名古屋工業大学や京都大学などが研究・開発を行い、日々進化を遂げている音声認識エンジンです。

現在(2020年10月)Juliusの最新バージョンは4.6です。

ですが、ディクテーションキットの最新バージョンが4.5だったのでJulius4.5で音声認識を行っていきます!

音声認識をしよう!

使用する機器

今回使用するのは

  • RaspberryPi 3B+
  • USBマイク

の2つです。私が使用したマイクは珍しい形のマイクでしたが、感度はかなり良かったです!ぜひ試してみてください!

https://amzn.to/355FzsX

https://amzn.to/2H9t0EX

音声設定

まず、マイクの音声設定を行います。

以下のコマンドをターミナルに入力してUSBが接続されていることを確認します。わからない場合は抜き差しして確認してみてください。

lsusb

デバイスの優先順位を確認します。以下のコマンドを入力してください。

#デバイスの優先順位を確認
cat /proc/asound/modules

0の方が優先度が高くなるので、snd_usb_audioを0に変更します。以下の操作を行ってください。

#nanoエディタを開く(ターミナルに入力)
sudo nano /etc/modprobe.d/alsa-base.conf

#以下のコードを入力してCtrl+X →Yで保存(nanoエディタの操作)
options snd slots=snd_usb_audio,snd_bcm2835
options snd_usb_audio index=0
options snd_bcm2835 index=1

USBの優先度が上がっていることを確認できました!

こうならない場合は再起動してみてください。

次に、初期設定を行っていきます。カード・デバイス番号を確認するために以下のコマンドを入力してください。

#カード番号とデバイス番号を確認
arecord -l 

デバイスの登録をします。

#0,0のところはご自身の(カード番号、デバイス番号)を入力してください
export ALSADEV="plughw:0,0"

これでUSBマイクの設定はできたのですが、毎回export ALSADEV="plughw:0,0"を入力しないといけません。以下の操作をして、起動時に常にこの設定になるようにします。

#nanoエディタを開く(ターミナルに入力)
sudo nano /etc/profile

#一番下に下記のコマンドを貼り付けてCtrl+X Yで保存
#さっきのコマンドと同じです。
export ALSADEV="plughw:0,0"

必要なライブラリのインストール

Juliusでサウンド、およびマイクを使用するために、ALSAサウンドドライバなどの必要なモジュールをインストールします。

LSAとはAdvanced Linux Sound Architectureの略称で,Linuxにおける高機能なサウンドシステムを提供するためのソフトウェア群です。

#Juliusで必要なモジュールのインストール
sudo apt-get install osspd-alsa
sudo apt-get install alsa-utils sox libsox-fmt-all

sudo sh -c "echo snd-pcm >> /etc/modules"
#すべての入力が終わったら一度再起動
sudo reboot

マイクの録音確認

マイクで録音できるか確認します。以下のコマンドを入力してください。

#録音確認
#コマンド入力後、録音が始まりCtrl+Cで終了
#test.wavファイルが生成されます
arecord -D plughw:0,0 test.wav

#録音音声再生(1,0はカード番号、デバイス番号)
#aplay -l で確認できます
aplay -D plughw:1,0 test.wavで再生してみる

無事、再生されれば確認完了です!

Juliusのセットアップ

下記のようなディレクトリになるよう、インストールしていきます。

説明する手順に従えば大丈夫です!

$ tree
Pi
└──julius
      ├──julius-4.5
      └──julius-kit

Juliusをインストールします。コンパイルには少し時間がかかります。

mkdir julius
cd julius

#Juliusバージョン4.5をダウンロード
wget https://github.com/julius-speech/julius/archive/4.5.tar.gz
tar xvzf 4.5.tar.gz
cd julius-4.5 
#Makeファイルを作成
./configure --with-mictype=alsa 
#コンパイルをします(JuliusプログラムはC言語で書かれているためコンパイルが必要)
make
#インストールします
sudo make install
makeでエラーが出た

実際にコンパイルする際このようなエラーが出ました。

make: *** [Makefile:57: libsent] エラー 1

この場合はもう一度./configure --with-mictype=alsaを実行してみてください。それで解決されると思います。

  • sudo apt-get install libsdl2-dev
  • sudo apt-get install libc6-dev

それでもできなければこの二つを試してみてください!

#Juliusディレクトリに戻る
cd ..
#Julius-kitディレクトリを作成
mkdir julius-kit
#Julius-kitに移動
cd julius-kit

ディクテーションキットをダウンロード、解凍します。これも時間がかかりますので、コーヒーでも飲みながら待ちましょう!

#ダウンロードするのは最新版の4.5
wget https://osdn.net/dl/julius/dictation-kit-4.5.zip
unzip dictation-kit-4.5.zip

Juliusで音声認識

いよいよ音声認識です!ディレクトリに注意して、下記コマンドを実行してください!

# ~/julius/julius-kit/dictation-kit-4.5/となるようにディレクトリを移動
cd dictation-kit-4.5

#下記コマンドで実行
julius -C main.jconf -C am-gmm.jconf -demo

上の画面になったら適当に話しかけてみましょう!

「おはようございます」などの簡単な言葉ならしっかりと聞き取ってくれます。

「生麦生米生卵」などのように、少し長めの文章になると精度が落ちるようです。

他のサイトで言われているように、かなり精度が悪いというわけでもなさそうです。辞書を使用しなくても簡単な言葉ぐらいなら余裕で認識できると思います!

Pythonで音声認識

音声認識で認識した音声を使って、Pythonで何かしたいですよね。

今回は簡単に、「特定の音声を認識したらprintでターミナルに表示する」という簡単な実装をしてみます。

Juliusをモジュールモードで起動すると、ソケット通信を介してデータをやりとりすることができます。

モジュールモード時のターミナル

ソケット通信とは

Juliusをモジュールモードで起動することで,Julius を音声認識サーバーとして動かすことができる.モジュールモードで起動された Julius は,TCP/IP 経由でクライアントと接続し,クライアントへの認識結果や音声イベントの送信,およびクライアントからの動作制御を行うことができる.クライアントとの接続は一対一を想定しており,複数クライアントの同時接続には対応していない.(Juliusbookより)

サーバー(Julius)、クライアント(Python)としてデータのやり取りを行うということです。

一連の流れを図で示すとこんな感じになります。

XMLのデータはこんな感じになっています。

Juliusbook第10章より

ソースコード

ファイル名を「julius.py」として保存します。Piの下に保存しておきましょう。

コードの内容はコメントを参照してください。

import socket
import time
 
def julius():
    host = '127.0.0.1'   # juliusサーバーのIPアドレス
    port = 10500         # juliusサーバーの待ち受けポート
    data_size = 1024     # 受信データバイト数
    # socket通信でjuliusサーバーに接続(接続要求)
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((host, port))

        strtemp = ""#話した言葉を格納する変数
        fin_flag = False #話終わりのフラグ
 
        time.sleep(3)#接続待ち
        while True:
            # juliusサーバからデータ受信
            data = s.recv(data_size).decode('utf-8')

            for line in data.split('\n'):
                # 受信データから、<WORD>の後に書かれている言葉を抽出して変数に格納する。
                # <WORD>の後に、話した言葉が記載されている。
                index = line.find('WORD="')
                if index != -1:#認識した文字列があれば
                    #strtempに話した言葉を格納
                    strtemp = strtemp + line[index+6:line.find('"',index+6)]
                # 受信データに</RECOGOUT>'があれば、話終わり ⇒ フラグをTrue    
                if '</RECOGOUT>' in line:
                    fin_flag = True
                if '<RECOGFAIL/> ' in line:
                    print("聞き取れませんでした")
                    fin_flag = False

            if fin_flag == True:
                if '電気' in strtemp:
                    print("電気をつけます")
                elif '誰' in strtemp:
                    print("juliusです")
                elif '歌' in strtemp:
                    print("歌えません")
                else:
                    print("話した言葉:" + strtemp)

                fin_flag = False
                strtemp = ""
                

if __name__ == "__main__":

    julius()

実際に動かしてみる

ターミナルを2つ起動します。一方はモジュールモード(サーバー)、一方はPython用(クライアント)です。

Juliusモジュールモード起動は、以下のコマンドで行います。-moduleを最後につけるだけです。

#dictation-kit-4.5まで移動
cd ~/julius/julius-kit/dictation-kit-4.5/

# -moduleでモジュールモード起動
julius -C main.jconf -C am-gmm.jconf -demo -module

実際に話しかけてみます!

おわりに

辞書などを作成していないのですが、思ったより反応はよかったです。しかし、2文字で設定した「だれ」や「うた」などは認識してくれませんでした。その代わり「誰ですか」、「歌ってください」のように話しかければしっかりと認識してくれました!

独自辞書を作成すれば、かなりの確率で認識してくれそうな予感です!

これは応用しがいがありそうですね。声でLEDをつけたり、カメラを動かしたりできそうです。私もSiriっぽいものをこれから作成していきたいと思っています!

今回はここまでです。最後までありがとうございました!

参考サイト

ありがとうございました。

スポンサーリンク

-Python