Raspberry Piで音声認識・音声合成する方法(Raspbian Jessie対応)

f:id:karaage:20170611164838j:plain:w640

2017/06/11 最新のRaspbian Jessieと最新のJuliusのバージョンに合わせて設定方法を修正し、Raspberry Pi 3で動作確認を行いました

Raspberry Piで音声認識・音声合成

 Raspberry Piで音声認識・音声合成をする方法です。基本的にはほぼネットで調べたことそのままですが、バージョンなどの関係で、自分の環境ではそのままじゃダメなところ等あったので、自分の備忘録としてまとめておきます。参考にしたサイトは参考リンクにまとめました。2017年6月時点ではこの記事の方法でそのまま動くはずです。

 Raspberry PiはRaspberry Pi 2/Raspberry Pi 3、OSはRaspbian Jessieを想定しています。

Raspberry Piの基本セットアップ

 Raspberry Piの基本的なセットアップは済んでいる前提です。セットアップに関しては、以下記事を参照ください。

 音声認識するためには、Raspberry Piに音声入力する必要がありますが、Raspberry Piには標準でマイクがついてないのでUSBマイクを接続する必要があります。マイクは以下がRaspberry Piで実績がありよいと思います。

SANWA SUPPLY MM-MCUSB16 USBマイクロホン

SANWA SUPPLY MM-MCUSB16 USBマイクロホン

 後、音声を確認するためにヘッドフォン(イヤフォンでも可)かアクティブスピーカを用意しましょう。

LOGICOOL ステレオスピーカー Z120BW

LOGICOOL ステレオスピーカー Z120BW

 音が出れば何でもよいのですが、どれを選べばよいかわからないという優柔不断な人へのオススメは上記のアクティブスピーカ。1500円の割によい音質で、電源もRaspberry PiのUSB電源から供給できてグッドです。

 これ以降に関しては、Raspberry Piの基本的なセットアップ完了した後、USBマイクとスピーカを接続してから起動している前提で解説します。宇宙語が続くので興味ある人だけ続きを読むをクリック下さい。

音声関係設定

 最初に音声入力(USBマイク)の設定を行います。Raspberry Piを起動してUSBマイクをRaspberry PiのUSBポートに接続したら、以下コマンドを実行しましょう。

$ lsusb

 以下のような文字がずらずらっとでてきます。マイクっぽいのがあったらOK。下の例だとBus 001 Device 005: ID 0d8c:0134 C-Media Electronics, Inc. となります。

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 0411:01ee BUFFALO INC. (formerly MelCo., Inc.) WLI-UC-GNM2 Wireless LAN Adapter [Ralink RT3070]
Bus 001 Device 005: ID 0d8c:0134 C-Media Electronics, Inc. 

 次に以下コマンドでUSBオーディオアダプタの優先度を以下コマンドで確認します。

$ cat /proc/asound/modules 

 実行結果は以下となりました

0 snd_bcm2835
1 snd_usb_audio

 数字が小さい方が優先度高いので、ここでは、usbオーディオアダプタsnd_usb_audioの優先順位が低いことがわかります。設定ファイルを変更して、優先度を変更してあげましょう。以下コマンドで設定ファイルを作成します(RaspbianのJessieのバージョンからは、ファイル変更でなく新規作成の必要があります)

$ sudo vi /etc/modprobe.d/alsa-base.conf 

 ファイルの中身は以下をそのままコピペしてください。options snd-usb-audio index=-2options snd-usb-audio index=0に書き換え。以下みたいな感じね

options snd slots=snd_usb_audio,snd_bcm2835
options snd_usb_audio index=0
options snd_bcm2835 index=1

 以下コマンドで再起動して設定を有効にしましょう。

$ sudo shutdown -r now

 再びUSBオーディオアダプタの優先度を確認しましょう。

$ cat /proc/asound/modules

 下記のように表示されれば、USBオーディオアダプタがちゃんと優先されています

0 snd_usb_audio
1 snd_bcm2835

 次に、以下コマンド実行してマイクの感度を調整します。

$ amixer sset Mic 50 -c 0

 コマンドの最後の-c 0はカードナンバです。最新のバージョンだとこれをつけないとamixer: Unable to find simple control 'Mic', 0というエラーが発生して動きませんでした。詳しくは以下のサイトが参考になりました。

Raspberry Piで音声認識 - Qiita

 Micの後の数字(上の例だと50)はマイクに応じて適宜調整しましょう。実行すると出てくる表示の最後の [81%]というのが感度です。自分の場合は80%くらいだとちょうど良い感じでした。

Simple mixer control 'Mic',0
  Capabilities: cvolume cvolume-joined cswitch cswitch-joined penum
  Capture channels: Mono
  Limits: Capture 0 - 62
  Mono: Capture 50 [81%] [16.59dB] [on]

 音声出力に関しては、お好きなスピーカをRaspberry Piのアナログ出力に接続してもらえばOKです。イヤホンなどでも大丈夫です。

音声録音・音声再生テスト

 音声録音と音声再生を試してみましょう。

音声録音

 まずは、音声録音の設定を確認します。以下コマンドでデバイスの設定を確認します。

arecord -l

 以下が実行結果です。

**** ハードウェアデバイス CAPTURE のリスト ****
カード 0: Device [USB PnP Audio Device], デバイス 0: USB Audio [USB Audio]
  サブデバイス: 1/1
  サブデバイス #0: subdevice #0

 音声録音のコマンドのデバイスは-D plughwというオプションで、以下のような形式でカードナンバとデバイスナンバを指定する必要があります(他のオプションに関しては、ヘルプなど参照ください)。

$ arecord -D plughw:[card, device]  -r 16000 -f S16_LE test.wav

 例えば先ほどの実行結果からは、 [0,0]を指定する必要があります。よって以下のコマンドでtest.wavというファイルを録音することができます。コマンドを実行した後、マイクに声を吹き込みましょう。吹き込み終わったらCtrl+Cで終了して下さい。

$ arecord -D plughw:0,0 -r 16000 -f S16_LE test.wav
音声再生

 音声再生に関しては、最初に以下のコマンドでデバイスの確認をします。

$ aplay -l

 以下実行結果です

**** ハードウェアデバイス PLAYBACK のリスト ****
カード 1: ALSA [bcm2835 ALSA], デバイス 0: bcm2835 ALSA [bcm2835 ALSA]
  サブデバイス: 8/8
  サブデバイス #0: subdevice #0
  サブデバイス #1: subdevice #1
  サブデバイス #2: subdevice #2
  サブデバイス #3: subdevice #3
  サブデバイス #4: subdevice #4
  サブデバイス #5: subdevice #5
  サブデバイス #6: subdevice #6
  サブデバイス #7: subdevice #7
カード 1: ALSA [bcm2835 ALSA], デバイス 1: bcm2835 ALSA [bcm2835 IEC958/HDMI]
  サブデバイス: 1/1
  サブデバイス #0: subdevice #0

 音声出力のコマンドは、例えば先ほど録音した「test.wav」というファイルを再生する場合は以下のような形式となります。

$ aplay -Dhw:[card, device] test.wav

 例えば上の場合だと、[1,0]がスピーカ出力のオーディオ、[1,1]がHDMIのオーディオとなる(名前から想像)ので、スピーカから音出したい場合は以下のように実行します。

$ aplay -Dhw:1,0 test.wav

 自分の声が聞こえてきたらOKです。

 Raspbianのデスクトップで操作できるなら、右上のスピーカのアイコンを右クリックして、以下のようにAnalogを選択する方法もあります。
f:id:karaage:20170611223046p:plain:w480

 上記のように設定してやれば、デフォルトの音声出力設定がラインアウトになるので、デバイス指定しなくても以下のコマンドで再生できます。

$ aplay test.wav

音声認識ソフト(Julius)ダウンロード

 Raspberry Piだとフリーの音声認識ソフトはJuliusが良いみたいです(自分が知る限りほぼ一択)。合わせて、ディクテーションの実行キットや、記述文法音声認識キットをダウンロードしておくのがよいでしょう。サイトは以下ですので、最新版を確認しておくと良いです。

GitHub - julius-speech/julius: Open-Source Large Vocabulary Continuous Speech Recognition Engine
 Juliusのサイト

GitHub - julius-speech/julius: Open-Source Large Vocabulary Continuous Speech Recognition Engine
 ディクテーション実行キットのサイト

GitHub - julius-speech/julius: Open-Source Large Vocabulary Continuous Speech Recognition Engine
 記述文法音声認識キットのサイト

 以下は、現時点(2017年6月)で最新のバージョンをダウンロードしてインストールする方法です。ソフトウェアバージョンに関しては、上記サイトで最新版を確認するのがよいと思います。

Juliusのインストール

 以下コマンドを実行すれば、ダウンロードとインストールができます。最新バージョンをダウンロードしたいときは、一番最初のコマンドを適宜読み替えてください。

$ wget --trust-server-names https://ja.osdn.net/projects/julius/downloads/66547/julius-4.4.2.tar.gz
$ tar xvzf julius-4.4.2.tar.gz
$ cd julius-4.4.2
$ ./configure
$ make
$ sudo make install
ディクテーション実行キット、記述文法音声認識キットのダウンロード

 以下コマンドでダウンロードできます。

$ mkdir ~/julius-kits
$ cd ~/julius-kits
$ wget --trust-server-names https://osdn.net/projects/julius/downloads/66544/dictation-kit-v4.4.zip
$ unzip dictation-kit-v4.4.zip
$ wget https://github.com/julius-speech/grammar-kit/archive/v4.3.1.zip
$ unzip v4.3.1.zip

 ただ、このまま音声認識実行しようとするとError: adin_oss: failed to open /dev/dspというエラーが発生するため、以下コマンドを実行しておきましょう。

$ sudo modprobe snd-pcm-oss

 再起動するたびに毎回上記コマンド実行するのも大変なので、以下を実行して/etc/modulessnd-pcm-oss書き込むと毎回実行する必要が無くなります。

$ sudo sh -c "echo snd-pcm-oss >> /etc/modules"
音声認識ソフトJuliusの動作確認

 以下コマンド実行すると音声認識のデモが動作します。

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

<<< please speak >>>と表示されたら、例えば「こんにちは」等としゃべって以下のように認識されればOKです。停止したいときはCtrl+Cを押して下さい。

### 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
pass1_best:  こんにちは 。
pass1_best_wordseq: <s> こんにちは+感動詞 </s>
pass1_best_phonemeseq: silB | k o N n i ch i w a | silE
pass1_best_score: -2970.963867
音声認識用の専用辞書作成

 決まった単語のみ認識するように、専用の辞書を作成しましょう。

 まずは、以下コマンドで基本となる辞書を作成します。

$ vi recog.yomi

 中身は例えば以下とします(読みはカタカナだとエラーがでるようなので注意下さい)。

檸檬ちゃん  れもんちゃん

 以下コマンドで、辞書をJuliusで読み込める形式に変換します。

$ iconv -f utf8 -t eucjp recog.yomi | yomi2voca.pl > ~/julius-kits/dictation-kit-v4.4/recog.dic

 次に、juliusの設定ファイルrecog.jconfを以下コマンドで作成しましょう。

$ vim ~/julius-kits/dictation-kit-v4.4/recog.jconf

 ファイルの内容は以下をコピペしてください。これで専用の辞書を読み込むようになります。設定内容に関しては、以下記事を参考にさせていただきました。

ラズパイで音声認識をしてみる | うしこlog

-w recog.dic       #単語辞書ファイル
-v model/lang_m/bccwj.60k.htkdic  #N-gram、または文法用の単語辞書ファイルを指定する
-h model/phone_m/jnas-tri-3k16-gid.binhmm #使用するHMM定義ファイル
-hlist model/phone_m/logicalTri   #HMMlistファイルを指定する
-n 5        #n個の文仮説数が見つかるまで検索を行う
-output 1     #見つかったN-best候補のうち、結果として出力する個数
-input mic      #マイク使用
-input oss      #オープンサウンドシステム使用
-rejectshort 600  #検出された入力が閾値以下なら棄却
-charconv euc-jp utf8 #入出力エンコード指定(内部euc-jp, 出力utf-8)
-lv 1000    #入力の振幅レベルの閾値(0~32767)

 以下コマンドで、専用の辞書を読み込む設定でjuliusを起動します

$ julius -C ~/julius-kits/dictation-kit-v4.4/recog.jconf

 辞書にある言葉をマイクに話して以下の表示が出たらOKです。

<input rejected by short input>
STAT: skip CMN parameter update since last input was invalid

pass1_best: 檸檬ちゃん    
pass1_best_wordseq: 檸檬ちゃん
pass1_best_phonemeseq: silB l e m o n c h a n silE
pass1_best_score: -2330.755615
sentence1: 檸檬ちゃん
wseq1: 檸檬ちゃん
phseq1: silB l e m o n c h a n silE
cmscore1: 1.000
score1: -2330.755615

 他のアプリケーションから音声認識を使いたいときは、juliusをモジュールモードで走らせる必要があります。モジュールモードにするには設定ファイルを変更します。ファイルを以下のコマンドで開き、末尾1行に-moduleを追加して閉じましょう

$ vi ~/julius-kits/dictation-kit-v4.4/recog.jconf


 あとは以下のコマンドを実行するとモジュールモードでjuliusが起動します。

$ julius -C ~/julius-kits/dictation-kit-v4.4/recog.jconf

 モジュールモードでの音声認識の使い方は、以下の例などを参考にして下さい。

Raspberry Piで音声合成

 音声合成は、ゆっくりの声に定評のあるAquestalk Piというソフトを使用します。以下のサイトの下の方にある「同意してダウンロード」をクリックしましょう(右側のサイドバーのDownloadではないので注意)。

Aquestalk Pi

 ダウンロードしたファイルをSFTP等を使ってRaspberry Piに転送しましょう。よくわからない人は、下記記事のファイル転送の箇所を参照ください。

 後は、ダウンロードしたファイルを解凍して、ディレクトリに移動して実行するだけです。

$ tar xvf aquestalkpi-20130827.tar
$ cd aquestalkpi
$ ./AquesTalkPi "こんにちは" |  aplay -Dhw:1,0

 これでしゃべってくれるはずです。簡単ですね。
 ちなみにAquestalkは、個人利用なら問題ないですが、商業用に使う場合はライセンス購入の必要がありますので注意下さい。

追記:Aquestalk Pi以外にも、フリーのOpen JTalkを使った音声合成も試してみました。ライセンスで困った方や他の方式も試してみたい方は参考にしてみて下さい。

まとめ

 これで一通りRaspberry Piの音声周りは整備できたことになります。これで色々できそうですね。具体的なアプリケーションに関しては、ちょっとしたものを作ったので、気が向いたらまた紹介します。

追記(2015/09/05)

作ってみたよ!