Juliusによる音声認識~国産オープンソースライブラリの活用 ラズベリーパイ研究室

オープンソース音声認識ライブラリ『Julius』の使い方を纏めました。
Raspberry PiのCPUはまだまだ遅いので文法ファイルを作成して利用するのが現実的のようです。



おススメ!記事
Raspberry Pi 用「HAL」で、
カップラーメン・タイマーを作ってみよう!
ラズパイDIYの決定版! ソケットサーバー「HAL」をご紹介します。

※誠に申し訳ありませんがこちらの電子工作のコンテンツは弊社の実験制作例となっております。十分な安全が保障されているわけではないため、参照や実施は自己責任となってしまいますのでご注意ください。

イントロダクション

 「Julius」は、日本の大学やIPAによって開発されているオープンソースの音声認識システムです。Raspberry Pi での音声認識の記事というと、大抵はこのJuliusを利用したもののようです。Google音声認識を利用した例もありますが、ライセンス的にかなり濃いグレーになりますので、ここではJuliusを使った音声認識を取り上げてみたいと思います。

バージョンについて

 Juliusの最新バージョンは4.3.1となっています。(2015/05/08現在)

 このバージョンでは比較的大きな変更が加えられているようで、Raspbarry Pi の多くの記事で取り扱っている4.2.x以前の記述では動作しないものがあります。この記事は4.3.1を対象しています。

ダウンロード

 まず、Julius本体をダウンロードします。

wget -O julius-4.3.1.tar.gz 'http://sourceforge.jp/frs/redir.php?m=osdn&f=%2Fjulius%2F60273%2Fjulius-4.3.1.tar.gz'

 Julius を使うためにはダウンロードしたソースファイルをコンパイルしなければなりませんので、以下のコマンドを順次実行します。

tar zxvf julius-4.3.1.tar.gz
cd julius-4.3.1/
./configure
make
sudo make install

 これで、Julius のコンパイルとインストールは完了です。

julius -version

 で、正しくインストールされているか確認してください。

 加えて、Julius の実行時に必要なカーネルモジュールを有効化します。

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

 併せて、ディクテーションキットと文法認識キットをダウンロードします。ディクテーションキットはディクテーション(自動口述筆記)に必要な最小限モデルが含まれたキット、文法認識キットは実用的な音声認識を行うために定型の文法を用いるためのキットです。

 Julius-4.3.1のディレクトリから抜けて、2つのキットをwgetします。こちらはコンパイルする必要はありません。解凍して julius-kits ディレクトリに纏めておきます。

cd ../
wget -O dictation-kit-v4.3.1-linux.tgz 'http://sourceforge.jp/frs/redir.php?m=jaist&f=%2Fjulius%2F60416%2Fdictation-kit-v4.3.1-linux.tgz'

wget -O grammar-kit-v4.1.tar.gz 'http://sourceforge.jp/frs/redir.php?m=osdn&f=%2Fjulius%2F51159%2Fgrammar-kit-v4.1.tar.gz'
tar zxvf dictation-kit-v4.3.1-linux.tgz
tar zxvf grammar-kit-v4.1.tar.gz

mkdir julius-kits

mv dictation-kit-v4.3.1-linux julius-kits/
mv grammar-kit-v4.1 julius-kits/

マイクのテスト

 音声認識をさせるためにはマイクが必要です。Raspberry Pi にはアナログマイク端子が無いのでUSBマイクを利用するのが一番効率が良いかと思います。

 弊社でテストしたマイクはこちらです。

音声認識率はどちらも大して変わらないようですが、下のものは全指向性なのと、ミュートボタンがあるので、常時音声認識をさせる場合にはすぐに切り替えが出来て便利だと思います。

 なお、アナログマイクを利用されたい場合はUSB変換アダプターを利用する方法もあります。変換アダプターはノイズが多い物がありますので、弊社がテストした中ではこちらがお勧めです。

Plugable® USB オーディオ変換アダプタ 3.5mm ヘッドホン・マイク端子付(黒アルミニウム仕上げ、C-Media社CM108 チップ採用、Windows、Mac、 Linux 対応)

 マイクをRaspberry Pi に刺し、オーディオカードの優先順位を確認します。

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

 上記の様に snd_usb_audio が上にあればUSBデバイスがオンボードのサウンドカードよりも優先されています。下にあった場合はUSBデバイスの優先度を上げておきます。

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

 で開いた設定ファイルの snd-usb-audio のインデックスが-2になっているかと思いますので、これを0にします。

#options snd-usb-audio index=-2

options snd-usb-audio index=0

 設定ファイルを保存して再起動すると、USBオーディカードが優先されているはずです。再び sudo cat /proc/asound/modules で優先順位を確認してください。

※2016/04/02追記 snd-usb-audioですが、snd_usb_audio となっている場合があるようです。編集の際は元のパラメターに併せて編集するようお願い致します。(上記はwheezyで確認した設定パラメターです)

 いよいよ録音テストです。まずマイクの音量を調節します。

amixer sset Mic 50

 最大音量は62ですので、録音と再生を繰り返しながらマイクに合った適切な数値を探ってください。

 最初に再生テストを行います。次のコマンドで、スピーカーのカード番号とデバイス番号を調べます。

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

 Raspberry Pi のアナログスピーカー端子はカード 1番、デバイス 0番、Raspberry Pi のHDMI端子はカード番号 1番、デバイス 1番です。

 HDMI端子は音の立ち上がりが遅いため、再生の最初が途切れてしまいます。このため、今回はアナログ端子でテストを行います。サンプルファイルを再生してみましょう。

aplay -D plughw:1,0 /usr/share/sounds/alsa/Front_Center.wav

 次に録音ですが、スピーカーの時と同様に

arecord -l

で、マイクデバイスのカード番号とデバイス番号を調べます。

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

 上記のようなリストが表示されると思います。接続してあるマイクはカード 0番、デバイス 0番ということがわかります。では録音してみましょう。

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

 録音を中止するにはCtrl + C を押してください。

 再生してみましょう。

aplay -D plughw:1,0 test.wav

 音声が再生されればマイクは正常に動作しています。

Juliusでの音声認識

 さて、では実際に Julius で音声認識です。最初はディクテーションキットを使って音声認識してみましょう。

cd julius-kits/dictation-kit-v4.3.1-linux
julius -C main.jconf -C am-gmm.jconf -demo

 このキットは特定の文法や単語の定義セットを用いずに音声を認識するのでかなり時間がかかります。高速なCPUを搭載したRaspberry Pi 2 Model B で、なんとか使えるかなといった速度です。

Raspberry Pi Model B+

Raspberry Pi 2 Model B

 このように自由文章ではかなり時間がかかるため、あらかじめ予想される文法を登録して認識速度を向上させます。

文法ファイル作成

 まず、voca ファイルに発音音素列を記述します。記述はローマ字で行います。(ヘボン式でも訓令式でも良いようです 2016/08/12追記 ヘボン式が良いようです)区切り文字は半角スペースです。

 %で始まる行は、カテゴリ登録です。この後、構文制約ファイルを作成するときに使います。

 "NS_B" と "NS_E" はそれぞれ文頭および文末の「無音区間」に対応する単語カテゴリで、文の最初と最後に必ず挿入する必要があります。

vi kaden.voca
% KADEN
テレビ t e r e b i
電気 d e n k i
% WO
を w o
% PLEASE
つけて t u k e t e
消して k e sh i t e
% NS_B
[s] silB
% NS_E
[s] silE

 次に、 構文制約を行うための grammar ファイルを作成します。

vi kaden.grammar
S      : NS_B KADEN_ PLEASE NS_E
KADEN_ : KADEN
KADEN_ : KADEN WO

 KADEN と KADEN WO の両方のエイリアスとして KADEN_ を定義しています。これにより「電気つけて」と「電気をつけて」の両方の音声に対し、1つの構文制約で対応できます。

 voca ファイルと grammar ファイルは基本的には一対になります。ですので同じ名前にしてください。

 両ファイルを作成したらコンパイルを行って .dfa ファイル、.term ファイル、 .dict ファイルを生成するのですが、コンパイルに用いるプログラム mkdfa.pl について、少し注意が必要です。grammar-kit-v4.1 及び julius-4.3.1/gramtools/mkdfa/ に付属している mkdfa.pl(から参照されるmkfa) は64bit OSの場合正しくコンパイルが行えないようですので、julius-4.3.1 に付属している32bit、64bit両対応のmkfa を利用する必要があります。このため、以下のコマンドで 64bit OS対応バージョンの mkfa と dfa_minimize をjulius-4.3.1/gramtools/mkdfa/ 内に上書きコピーします。(2016/05/07追記 Raspberry Pi の OS は今のところ 32bit版のようです。コンパイル出来ないのは単純にソースコードのバグが原因かもしれません。すみませんでした)

cp julius-4.3.1/gramtools/mkdfa/mkfa-1.44-flex/mkfa julius-4.3.1/gramtools/mkdfa/mkfa

cp julius-4.3.1/gramtools/dfa_minimize/dfa_minimize julius-4.3.1/gramtools/mkdfa/dfa_minimize

 ではコンパイルしてみましょう。

sudo julius-4.3.1/gramtools/mkdfa/mkdfa.pl kaden

 上手く変換が出来た場合は kaden.dfa kaden.term kaden.dict の3ファイルが作成されます。kaden.dfa ファイルは「有限状態オートマトンに変換したもの」だそうで、構文制約によって定義される発音音素の遷移パターンのようです。kaden.term と kaden.dict の数値がこれに対応するようですが、詳しい仕様はThe Juliusbookを参照してください。

 では、作成した .dfa ファイルを用いて音声認識を行ってみます。

julius -C julius-kits/grammar-kit-v4.1/hmm_mono.jconf -input mic -gram kaden

 ディクテーションキットをそのまま使う場合と比べてほぼ実用的な速度になっていると思います。なお、音声認識に用いる文法ファイルですが、以下の様にカンマ区切りで複数列挙すれば同時に利用することも可能です。

julius -C julius-kits/grammar-kit-v4.1/hmm_mono.jconf -input mic -gram kaden,fruit

この記事へのコメント

※現在コメントはMarkdown記法が強制です。>>Markdown の書き方


オーディオカードの優先順位設定記述内の間違いについて

お名前:benrywaka

2016-04-01 10:27:33

各ステップが省略されることなく詳細に解説されていて、とても参考になりました。 ただ、 「snd-usb-audio のインデックスが-2になっているかと・・」以降の設定ファイル内の ``` #options snd-usb-audio index=-2 options snd-usb-audio index=0 ``` の部分は、snd\_usb\_audio の間違いのようですね。初心者の私はこれで1時間以上ハマってしまい、睡眠時間を削ってしまいました(笑) 私みたいな方がおられるかも知れませんので、修正いただけたらと思います。

お名前:benrywaka

2016-04-01 10:31:16

自己レスです。 先のコメント内の文字が化けて正しく表示されていませんでした。正しくは snd\_usb\_audioでした。失礼しました。

お名前:管理者ウェブサイト

2016-04-02 20:05:00

>benrywakaさん コメントありがとうございます。とてもうれしいです。 > 先のコメント内の文字が化けて正しく表示されていませんでした。正しくは sndusbaudioでした。失礼しました。 申し訳ありません。 説明が無いので混乱されたかと思いますが、このコメントフォームではMarkdown記法が適用されるようになっています。 アンダースコアで囲まれた文字列はMarkdownでは斜体タグに置き換えられるのでアンダースコアが消えて中身が斜体になってしまっていました。コメントの方、修正させていただきました。申し訳ありませんでした。 ``` snd-usb-audio ``` の件ですが、これは間違いではなく、どうもハイフンとアンダースコアの両方のパターンがあるようです。 詳しいことはよく分からないのですが、wheezyとjessieの違い(RaspbianのベースになっているDebianのコードネーム)の違いからくるのかもしれません。 私の記事はwheezyの時に書いたものですが、ひょっとしたらbenrywakaさんのOSはRaspbianのjessieではございませんでしょうか? もしそうでしたら、そのように追記しようと思います。 併せて、Markdownについての注意書きも加えようと思っています。

お名前:benrywaka

2016-04-10 17:01:49

早々に修正いただいていたのに、お返事遅くなりまして申し訳ありません。あれからRaspberryPiの音声認識や音声合成などの情報を求めてあちこちさまよっていました(^^;) 当方Raspberry Pi 2で使用中のOSを hostnamectl で表示してみたところ、 Operating System: Raspbian GNU/Linux 8 (jessie) Kernel: Linux 4.1.19-v7+ Architecture: arm ということで jessie 的中でした。 「Markdown」? またまた「初めまして」状態の用語です(笑) これからも勉強させていただきます。

お名前:管理者ウェブサイト

2016-04-10 18:21:48

>benrywakaさん お返事ありがとうございます。やはり、jessieでセッティングが変わっているっぽいですね。 Markdownは簡単な記述でHTMLを生成でき、掲示板などではセキュリティも担保できるので便利なものなんですが、普通は「Markdownを使う」みたいなチェックボックスがあって、それで有効にするものです。 このサイトのコメントフォームは突貫工事でつくったものなので、Markdownを強制してしまっていてあまり褒められたものじゃないんです。本当に申し訳ありません。 いま作っているプロダクトが出来上がったら、サイト自体に手を加えたいとは思っています。

この記事に返信

このコメントに返信