Penta creation

ホームへ
2016年12月23日

Raspberry Pi 3Bで音声認識

開発中のスマートミラーを音声認識で操作できるように、Raspberry Pi 3Bで音声認識エンジン(Julius)を試してみました。まずはUSBマイクから音声を入力できるようにします。

USBマイクから音声入力

最初にRaspberry Piに音声制御のライブラリをインストールします。

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

● USBマイクの接続

USBマイクはスマートミラーの筐体の中に収納することを考慮して、小型コンデンサーマイク「M071-SF-555-BLK」を使用、マイクをUSBポートに接続して「$ lsusb」コマンドで認識されているかを確認します。
※「C-Media Electronics, Inc. CM108 Audio Controller」がUSBマイクです。

$ lsusb

Bus 001 Device 004: ID 0d8c:013c C-Media Electronics, Inc. CM108 Audio Controller
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. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

● USBマイクの設定

モジュールの優先順位を変更します。「$sudo nano /proc/asound/modules」でモジュールの優先順位を確認すると「1 snd_usb_audio」となっているので、

$sudo nano /proc/asound/modules

0 snd_bcm2835
1 snd_usb_audio

USBマイクの入力を優先させるため「/etc/modprobe.d/alsa-base.conf」を新規作成し、下記のように設定します。

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

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

設定したらRaspberry Piを再起動します。
再度確認すると、USBマイクの優先度が上がっています。

$ sudo nano /proc/asound/modules

0 snd_usb_audio
1 snd_bcm2835

● 音声の入力確認

USBマイクは設定できたので、音声を入力(録音)してみます。音声の録音にはカード番号とデバイス番号を調べる必要があるので、「arecord -l」コマンドで確認します。

$ arecord -l

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

「カード 0 デバイス 0」なので「arecord -D」コマンドで録音をします。

$ arecord -D plughw:0,0 -d 10 -f cd test.wav
※「plughw:0,0」の「0,0」はマイクのカード番号とデバイス番号。

コマンドを実行すると「録音中」と録音が始まり、「Ctr+C」で録音を終了します。
作成した音声ファイル「test.wav」は「/home/pi/」に隠しファイルとして保存されるので、「隠しファイルを表示」でファイルを見つけて、PCなどで再生してみて、音声が録音されていたらOKです。

Juliusのインストールと起動

USBマイクが設定できたので、次に音声認識エンジンJuliusをインストールします。

● インストール

JuliusのダウンロードページでURLを調べて「julius-4.4.2.tar.gz」をダウンロード、解凍します。
※現時点で最新のjulius-4.4.2.tar.gzをインストールします。

$ wget 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

解凍したら「julius-4.4.2」ディレクトリに移動、「./configure」をたたき、「make」、「sudo make install」でインストールします。

$ julius -version

「julius -version」コマンドで、バージョン情報が出ればインストール成功です。

● ディクテーションキットと文法認識キットのダウンロード

ディクテーションキットと文法認識キットをダウンロードして、「julius-kits」ディレクトリを作成、「julius-kits」ディレクトリ内に解凍します。

$ wget https://osdn.net/projects/julius/downloads/66544/dictation-kit-v4.4.zip
$ wget https://osdn.net/projects/julius/downloads/51159/grammar-kit-v4.1.tar.gz

$ mkdir /home/pi/julius-kits
$ cd /home/pi/julius-kits

$ unzip /home/pi/dictation-kit-v4.4.zip
$ tar xvzf /home/pi/grammar-kit-v4.1.tar.gz

● 起動

カード番号を環境変数に設定、snd-pcm-ossモジュールを組み込んで、ディクテーションキットのディレクトリに移動してjuliusを起動します。

#カード番号を環境変数に設定
$ export ALSADEV=hw:0

#snd-pcm-ossモジュールを組み込む
$ sudo modprobe snd-pcm-oss

#ディクテーションキットのディレクトリに移動
$ cd /home/pi/julius-kits/dictation-kit-v4.4

#juliusの起動
$ julius -C main.jconf -C am-gmm.jconf -demo

起動に成功すると、下記のように音声入力画面になります。

----------------------- System Information end -----------------------

Notice for feature extraction (01),
	*************************************************************
	* Cepstral mean normalization for real-time decoding:       *
	* NOTICE: The first input may not be recognized, since      *
	*         no initial mean is available on startup.          *
	*************************************************************

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 >>>

成功したら、次回Raspberry Pi起動時に「snd-pcm-oss」が自動的に起動するように「/etc/modules」に「snd-pcm-oss」を追加しておきます。

$ sudo nano /etc/modules

#「snd-pcm-oss」を追加する
snd-pcm-oss

Juliusの設定

今回は、音声コマンドでスマートミラーを制御するのが目的なので、音声コマンド用のワードを辞書に登録して、Juliusで認識できるようにします。

● 辞書の作成

「julius-kits」ディレクトリに移動し、辞書ファイル「mirror.yomi」を作成して、音声コマンド用のワードを登録します。※「ハロー」と「はろぉ」の間はタブなので注意が必要です。

$ cd /home/pi/julius-kits
$ sudo nano mirror.yomi

ハロー   はろぉ
ウェイクアップ   うぇいくあっぷ
シーユー   すぃゆぅ
エンド   えんど
ネクスト   ねくすと
バック   ばっく
レフト   れふと
ライト   らいと
アップ   あっぷ
ダウン   だうん
マップ   まっぷ
ツイッター   つぃったぁ

音声コマンド用のワードを登録したら、「mirror.yomi」を「mirror.dic」に変換します。

$ iconv -f utf8 -t eucjp mirror.yomi | /home/pi/julius-kits/grammar-kit-v4.1/bin/yomi2voca.pl > mirror.dic

julius用の設定ファイル「mirror.jconf」を作成します。

$ sudo nano mirror.jconf

-w base_dict.dic
-input mic
-charconv euc-jp utf8
-h model/phone_m/jnas-tri-3k16-gid.binhmm
-hlist model/phone_m/logicalTri
-output 1

juliusを起動します。試してみると、発音が似ているものは誤認識してしまうようなので、音声コマンド用のワードの選択と辞書ファイルのチューンアップは必要ですが、ちゃんと認識されました!

$ julius -C mirror.jconf

----------------------- System Information end -----------------------

Notice for feature extraction (01),
	*************************************************************
	* Cepstral mean normalization for real-time decoding:       *
	* NOTICE: The first input may not be recognized, since      *
	*         no initial mean is available on startup.          *
	*************************************************************

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:エンド
pass1_best _phonemeseq:silB e N d o silE
pass1_best _score:-2295.860840
sentence1:エンド
wseq1:エンド
phseq1:silB e N d o silE
cmscore1:0.997
score1:-2295.860840
<<< please speak >>>

Processingとの連携

最後にjuliusとProcessingを連携させます。

● juliusをモジュールモードで起動

juliusにはモジュールモードがあり、モジュールモードで起動すると、音声認識の結果をWEBサーバーを立ち上げ、XML形式で出力してくれます。※モジュールモードで立ち上げると、ブラウザでhttp://localhost:10500にアクセスすると、文字化けしますが出力結果を見ることができます。

$ cd /home/pi/julius-kits/dictation-kit-v4.4

#-moduleをつけてモジュールモードで立ち上げ
$ julius -C mirror.jconf -module

● Processingで音声認識の結果を取得

juliusをモジュールモードで立ち上げた後、Processingで音声認識の結果を取得します。

import processing.net.*;

Client juliusClient;
String voiceCommand="";

void setup(){

  size(500,500);
  juliusClient = new Client(this,"localhost",10500);
}

void draw(){

  voiceCommand = getVoiceCommand();
  if(voiceCommand != ""){
    println(voiceCommand);
  }
}

String getVoiceCommand(){

  String command = "";
  if(juliusClient.available()>0){
    String words = juliusClient.readString();
    String[] wordsList = split(words,"WORD");

    for(int i=1; i < wordsList.length; i++){
      String tmpWord = wordsList[i];
      String[] commandList = split(tmpWord,'"');
      command += commandList[1];
    }
  }
  return command;
}
前の記事へ

Raspberry Pi 3Bで温度センサー(MCP9808)

次の記事へ

Raspberry Pi 3BでGoogle Assistant SDK

ページトップへ