Raspberry Piにマイクを付けて話した日本語を認識させたいと思います。
いくつか参考になるサイトがありましたが、自分の環境と微妙に異なってはまっていたのでまとめておきます。
##参考サイト
- 日本語音声認識
- RaspberryPIにUSBマイクで音声入力
- Raspberry Piで録音再生
- Raspberry PiでJuliusを使った音声認識(1)
- ALSA で snd_pcm_dmix_open が unable to open slave になる場合
- Can't set default sound device with ALSA [SOLVED]
##使った機器
- 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
を書き換えます。
:
# Keep snd-usb-audio from beeing loaded as first soundcard
options snd-usb-audio index=-2
:
となっているところを
:
# 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に
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だったのでその情報も記載しておきます。
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秒かかるのと、誤認識も多いという問題がありました。
改善する方法の一つを紹介しておきます。