Raspberry Piで音声認識

  • 157
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

Raspberry Piにマイクを付けて話した日本語を認識させたいと思います。
いくつか参考になるサイトがありましたが、自分の環境と微妙に異なってはまっていたのでまとめておきます。

参考サイト

使った機器

  • Raspberry Pi 2 Model B
  • SANWA SUPPLY MM-MCUSB16 USBマイクロホン
  • ELECOM USB3.0ハブ ACアダプター付き セルフパワー サイドポート付き 4ポート ブラック U3H-A408SBK
  • BUFFALO 無線LAN子機 コンパクトモデル 11n技術・11g/b対応 WLI-UC-GNM
  • ELECOM MS-P06U コンパクトスピーカー/USB電源

USBマイクの確認

まずUSBマイクが認識されるか確認します。

ライブラリのインストール

$ sudo apt-get install alsa-utils sox libsox-fmt-all

apt-getで失敗する場合、パッケージが古い可能性があるので最新にしておきましょう。

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo rpi-update

404 Not Foundが発生する場合は、Raspberry Pi -> Mac -> Internet環境でsudo apt-get update時に404 Not Foundもご覧ください。

USBポートの確認

lsusbを実行します。

$ lsusb
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 0d8c:0134 C-Media Electronics, Inc.
Bus 001 Device 005: ID 2109:2812
Bus 001 Device 006: ID 0411:01a2 BUFFALO INC. (formerly MelCo., Inc.) WLI-UC-GNM Wireless LAN Adapter [Ralink RT8070]

C-Media Electronics, Inc.というやつがUSBマイクです。
ラズパイのUSBポートに挿している状態です。

なぜかUSBバスの方に挿し込むと認識されませんでした。(無線LANはUSBバスでも認識されています)

オーディオモジュールの優先順位の確認

cat /proc/asound/modulesを実行し、モジュールの優先順位を確認します。

$ cat /proc/asound/modules
 0 snd_bcm2835
 1 snd_usb_audio

USB入力を優先させるため、/etc/modprobe.d/alsa-base.confを書き換えます。

/etc/modprobe.d/alsa-base.conf
:
# Keep snd-usb-audio from beeing loaded as first soundcard
options snd-usb-audio index=-2
: 

となっているところを

/etc/modprobe.d/alsa-base.conf
: 
# Keep snd-usb-audio from beeing loaded as first soundcard
#options snd-usb-audio index=-2
options snd-usb-audio index=0
: 

に変更します。

一旦リブートします。

$ sudo reboot

再度確認すると次のようになります。

$ cat /proc/asound/modules
 0 snd_usb_audio
 1 snd_bcm2835

マイクボリューム調整

マイクボリュームが小さいと声が拾えないのでボリュームを調整します。

$ amixer sset Mic 16 -c 0
Simple mixer control 'Mic',0
  Capabilities: cvolume cvolume-joined cswitch cswitch-joined penum
  Capture channels: Mono
  Limits: Capture 0 - 62
  Mono: Capture 62 [100%] [22.50dB] [on]

16というのがボリュームです。62で最大ボリュームです。

-c 0というのはカードNoです。

オプションなしで実行するとエラーが出ました。

$ amixer sset Mic 62
amixer: Unable to find simple control 'Mic',0

ヘルプを見るとカードNoを指定できることがわかったのでオプションに付けたところボリュームを変更できました。

$ amixer -h
Usage: amixer <options> [command]

Available options:
  -h,--help       this help
  -c,--card N     select the card
  -D,--device N   select the device, default 'default'
  : 

カードNoの調べ方は次の通りです。

$ arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: Device [USB PnP Audio Device], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

私の環境では、card 0 device 0です。

後でわかったのですが、~/.asoundrcに

~/.asoundrc
defaults.ctl.card 1

ctl.!default {
  type hw
  card 1
}

という記述を入れていためデフォルトがカード1になっていました。
card 0に変更するとamixer sset Mic 62でもボリューム変更できます。

録音してみる

マイクの設定が終わったので録音してみます。

$ arecord -D plughw:0,0 -d 10 -f cd test.wav

plughw:0,0の0,0はマイクのカードNoとデバイスNoです。(私の環境では0と0)

録音したファイルは、Macにscpでとってきて再生しました。
(Raspberry Piにスピーカーを付けて再生させるのも設定が必要だったので後述を参照してください)

$ scp pi@192.168.xxx.xxx:~/test.wav .
$ afplay test.wav

Raspberry Piで再生してみる

先ほど録音したファイルを再生します。

$ aplay test.wav
ALSA lib pcm_dmix.c:1018:(snd_pcm_dmix_open) unable to open slave
aplay: main:682: audio open error: No such file or directory

エラーが出たのでデバイスを確認してみます。

$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 1: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]
  Subdevices: 8/8
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
  Subdevice #2: subdevice #2
  Subdevice #3: subdevice #3
  Subdevice #4: subdevice #4
  Subdevice #5: subdevice #5
  Subdevice #6: subdevice #6
  Subdevice #7: subdevice #7
card 1: ALSA [bcm2835 ALSA], device 1: bcm2835 ALSA [bcm2835 IEC958/HDMI]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

出力のデバイスはcard 1にありました。

この情報を~/.asoundrcに記載します。
入力のUSBマイクはcard0だったのでその情報も記載しておきます。

~/.asoundrc
defaluts.pcm.card 1
defaults.ctl.card 0

pcm.!default {
  type hw
  card 1
}

ctl.!default {
  type hw
  card 0
}

配置できたらalsa-utilsを再起動します。

$ sudo /etc/init.d/alsa-utils restart

もう一度再生してみます。

$ aplay test.wav
Playing WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo

今度はうまく再生できました。

※単にスピーカー出力を試すだけなら次の方法でも良いかと思います。

$ aplay /usr/share/sounds/alsa/Front_Center.wav
$ speaker-test -t sine -f 600

Juliusの設定

音声認識エンジンとしてJuliusを使うことにしました。
(Google Speech APIも魅力的ですが、1日の利用回数制限があったので、今回はやめました。)

インストール

本家サイトからソースを取得しコンパイルします。

$ wget --trust-server-names 'http://osdn.jp/frs/redir.php?m=iij&f=%2Fjulius%2F60273%2Fjulius-4.3.1.tar.gz'
$ tar xvzf julius-4.3.1.tar.gz
$ cd julius-4.3.1/
$ ./configure
$ make

同じくディクテーションファイルも取得します。
(実はこちらにもビルド済みのjuliusがバンドルされているので、そちらを使っても良いと思います)

$ mkdir ~/julius-kits
$ cd ~/julius-kits
$ wget --trust-server-names 'http://osdn.jp/frs/redir.php?m=iij&f=%2Fjulius%2F60416%2Fdictation-kit-v4.3.1-linux.tgz'
$ tar xvzf dictation-kit-v4.3.1-linux.tgz

Juliusの実行

$ ALSADEV="plughw:0,0" ~/julius-4.3.1/julius/julius -C ~/julius-kits/dictation-kit-v4.3.1-linux/main.jconf -C ~/julius-kits/dictation-kit-v4.3.1-linux/am-gmm.jconf -nostrip

起動コマンドはdictation-kit-v4.3.1-linux/run.shの中を参考にしました。

plughw:0,0の0,0はマイクのカードNoとデバイスNoです。(私の環境では0と0)

もし

Stat: adin_oss: device name = /dev/dsp (application default)
Error: adin_oss: failed to open /dev/dsp

というエラーが発生した場合は、

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

を実行します。

-charconv EUC-JP UTF-8というオプションをつけて実行すると

InternalError: codeconv: invalid multibyte sequence in the input

というエラーが発生していました。

再起動後、Juliusを実行します。

$ ALSADEV="plughw:0,0" ~/julius-4.3.1/julius/julius -C ~/julius-kits/dictation-kit-v4.3.1-linux/main.jconf -C ~/julius-kits/dictation-kit-v4.3.1-linux/am-gmm.jconf -nostrip

 : 

### read waveform input
Stat: adin_oss: device name = /dev/dsp (application default)
Stat: adin_oss: sampling rate = 16000Hz
Stat: adin_oss: going to set latency to 50 msec
Stat: adin_oss: audio I/O Latency = 32 msec (fragment size = 512 samples)
STAT: AD-in thread created
<<< 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: -2942.340820
### Recognition: 2nd pass (RL heuristic best-first)
STAT: 00 _default: 14430 generated, 1278 pushed, 264 nodes popped in 122
sentence1:  こんにちは 。
wseq1: <s> こんにちは+感動詞 </s>
phseq1: silB | k o N n i ch i w a | silE
cmscore1: 0.440 0.458 1.000
score1: -2959.848633

<<< please speak >>>

うまく認識できました。

認識時間と認識率を高める工夫

ここまでの設定ではマイクで話してから認識するまでに2-3秒かかるのと、誤認識も多いという問題がありました。
改善する方法の一つを紹介しておきます。

Raspberry Piで音声認識(パフォーマンス改善)