Raspberry Pi+Juliusで音声を認識する


はじめに

Raspberry Piにマイクを接続して、話しかけた音声を認識させてみます。
音声認識には国産ツールの「Julius」を使用します。

用意するもの

  • Raspberry Pi 3
  • USBマイク

USBマイクは、マイク付きWebカメラでも利用できます。
ということで、今回はLogicool C300というUSB接続のWebカメラを使います。
https://www.amazon.co.jp/%E3%83%AD%E3%82%B8%E3%82%AF%E3%83%BC%E3%83%AB-C300-%E3%82%A6%E3%82%A7%E3%83%96%E3%82%AB%E3%83%A0/dp/B002J4UAG4

手順

Raspberry Piで音声認識をするにはJuliusの導入のほか、マイク関連の設定が必要にです。大まかな手順は下記の通りです。

  1. USBマイクをRaspberry Piで使う準備をする
  2. 録音のテスト
  3. Juliusをインストールする
  4. Julius音声認識パッケージを取得する
  5. 動作確認

USBマイクをRaspberry Piで使う準備をする

Raspberry PiにUSBマイクを認識させる

Raspberry Pi3と現在(3/28時点)でのRaspbianであれば、Logicool C300はUSBに接続するだけでデバイスを認識します。正しく認識されているかは、下記コマンドで確認できます。

コマンド
lsusb
lsusb実行結果
Bus 001 Device 004: ID 046d:0805 Logitech, Inc. Webcam C300   
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

上記の実行結果では、「Bus 001 Device 004」で「Logitech, Inc. Webcam C300」と表示されているため、WebカメラがUSBデバイスとして認識されていることがわかります。

USBマイクの優先順位をあげる

Raspberry Pi 3には、Φ3.5オーディオ出力端子が搭載されています。USBにスピーカー/マイクを接続しても、標準のオーディオ出力端子が優先されるため、USB側のスピーカー/マイクを認識してくれません。
これを解決するためには、オーディオデバイスの優先順位を変更する必要があります。
現在の優先順位を確認するには、下記のコマンドを実行します。

コマンド
cat /proc/asound/modules
実行結果
 0 snd_bcm2835
 1 snd_usb_audio

実行結果は、左から「優先順位(数値が低いほうが優先順位が高い)」、「デバイス名」の順で表示されます。上記の結果では、USBスピーカー/マイク(snd_usb_audio)がΦ3.5オーディオ出力端子(snd_bcm2835)よりも下であることがわかります。

これを変更するには、/lib/modprobe.d/aliases.confに記載の設定を変更します。
viなどのテキストエディタでファイルをしましょう。(root権限の付与を忘れずに)

sudo vim /lib/modprobe.d/aliases.conf 

ファイル内のoptions snd-usb-audio index=-2という箇所がUSBスピーカー/マイクの設定ですので、こちらの設定を「-2」から「0」を変更します。

変更後の/lib/modprobe.d/aliases.conf
# prevent unusual drivers from appearing as the first sound device ###########
options snd-pcsp index=-2
# options snd-usb-audio index=-2    # USB audio before 
options snd-usb-audio index=0       # USB audio after
options cx88_alsa index=-2
options snd-atiixp-modem index=-2
options snd-intel8x0m index=-2
options snd-via82xx-modem index=-2

設定ファイルを保存したら、Raspberry Piを再起動します。再起動後、再度cat /proc/asound/modulesを実行し、下記のように優先順位が変わっていれば、設定変更が有効になっています。

設定変更後のオーディオデバイスの優先順位
 0 snd_usb_audio
 1 snd_bcm2835

録音のテスト

Raspberry PiとUSBマイクが正しく動作することを確認するため、USBマイクから音声を録音し、ファイルに保存してみます。
音声の録音はarecordコマンドで実現できますが、arecordコマンドで録音するにはUSBマイクに割り当てられている「カードNo.」と「デバイスNo.」を知る必要があります。それぞれの確認は、arecordコマンドの-lオプションで確認できます。

カードNo.の確認
arecord -l
実行結果
**** List of CAPTURE Hardware Devices ****
card 0: U0x46d0x805 [USB Device 0x46d:0x805], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

上記の場合、「card 0」「device 0」と表示されているため、カードNo.、デバイスNo.ともに「0」で認識されているということがわかります。

カードNo.、デバイスNo.がわかったところで、arecordを使って録音した音声をファイルに保存します。録音するコマンドは下記のとおりです。

カードNo.の確認
arecord -D plughw:0,0 test.wav

コマンド実行後、録音待ちの状態になります。マイクに向かって話しかけ、完了したらCtrl+Cを押下して終了します。終了時に、下記のようなメッセージが表示されますが、中断した際に表示されるメッセージですので、問題ありません。

Aborted by signal Interrupt...
arecord: pcm_read:2103: read error: Interrupted system call

録音されたファイル(test.wav)を再生してみましょう。音楽プレイヤーなどのソフトで話しかけた音声を聞くことができれば、成功です。

Juliusのインストール

Juliusは、GitHubよりソースコードを取得し、ビルドすることでバイナリファイルを作成します。
公式ドキュメントにはバイナリパッケージを取得してインストールできるという記載がありますが、Githubで公開されているバイナリパッケージはWindows用のみで、Linuxなどで使用する場合は、ソースコードからコンパイルする必要があります。いずれMac/Linux環境用のバイナリパッケージも配布してほしいですね。

Juliusのソースコードの取得する

GithubのJuliusのサイトからソースコードを取得しましょう。下記のコマンドで取得できます。

mkdir julius
cd julius
wget https://github.com/julius-speech/julius/archive/v4.4.2.1.tar.gz

ソースコードをコンパイルする

下記のコマンドを実行し、ソースコードからバイナリパッケージをコンパイルします。コンパイルには時間がかかりますので、少し待ちましょう。

tar xvzf v4.4.2.1.tar.gz
cd julius-4.4.2.1
./configure
make

Julius音声認識パッケージを取得する

Juliusで音声認識をするためには、音声認識パッケージをインストールする必要があります。音声認識パッケージは公式サイトより取得します。
公式サイトでは用途に応じて複数のパッケージを提供していますが、今回は、一般的な日本語の音声認識であるディクテーションキット(dictation-kit)を使用します。
ディクテーションキットの取得は、下記コマンドで行います。

mkdir ~/julius/julius-kit
cd ~/julius/julius-kit
wget https://osdn.net/dl/julius/dictation-kit-v4.4.zip
unzip dictation-kit-v4.4.zip

その他環境設定

ALSADEV設定でデバイスを固定にする

Juliusを実行する際にもカードNo.、デバイスNo.の情報が必要です。Juliusが常に同じ設定を使用できるように、環境変数として設定しておくと便利です。
Raspberry Piの場合、~/.profileに下記の一文を追加します。

.profile
export ALSADEV="plughw:0,0"

変更を有効にするには、Raspberry Piを再起動、または「source ~/.profile」を実行します。
※この後の手順でRaspberry Piを再起動するため、ここでの再起動上記コマンドの実行は不要です。

/dev/dspを有効にする

JuliusではALSAサウンドドライバのデバイスファイル/dev/dspを使用します。標準では使用できるようになっていないため、下記のコマンドで利用できるようにします。(有効にするために再起動をしています)

sudo modprobe snd-pcm-oss
sudo sh -c "echo snd-pcm-oss >> /etc/modules"
sudo reboot

ここまでで、Juliusの環境構築は完了です。

動作確認

ディクテーションキットの解凍が完了したら、いよいよJuliusを動かします。起動のコマンドは下記のとおりです。

~/julius/julius-4.4.2.1/julius/julius -C ~/julius/julius-kit/dictation-kit-v4.4/main.jconf -C ~/julius/julius-kit/dictation-kit-v4.4/am-gmm.jconf -nostrip

Juliusの起動が成功すると<<< please speak >>>と表示されます。
試しに「こんにちは」とマイクに向かって話しかけてみましょう。
音声認識が成功すると、下記のように表示されます。

pass1_best:  こんにちは 。
pass1_best_wordseq: <s> こんにちは+感動詞 </s>
pass1_best_phonemeseq: silB | k o N n i ch i w a | silE
pass1_best_score: -4168.268555
### Recognition: 2nd pass (RL heuristic best-first)
STAT: 00 _default: 21946 generated, 1540 pushed, 319 nodes popped in 159
sentence1:  こんにちは 。
wseq1: <s> こんにちは+感動詞 </s>
phseq1: silB | k o N n i ch i w a | silE
cmscore1: 0.351 0.416 1.000
score1: -4188.954102

おわりに

Juliusの導入は想像以上に簡単にできました。どちらかというと、USBマイクを認識するためにOS側の設定変更のほうが大変でした。
それと、今回使用しているディクテーションキットの認識率ですが、Google Cloud Speech API等に比べると精度は劣るように思います(辞書の精度に大きな差があるのでしょうね)。その分、通信のオーバーヘッドがない分応答速度は早いので、用途に応じて使い分けるということになりそうです。