気の向くままに辿るIT/ICT/IoT
IoT・電子工作

Julius / Open JTalkスマートスピーカーで OSS/ALSA/PulseAudio

ホーム前へ次へ
Raspberry Piって?

Julius / Open JTalkスマートスピーカーで OSS/ALSA/PulseAudio

Julius / Open JTalkスマートスピーカーで OSS/ALSA/PulseAudio

2019/06/02

 以前、作って運用しつつもブラッシュアップ中のRaspberry Pi 3 Model B+とJuliusOpen JTalkベースの自作スマートスピーカーがあります。

 主な機能は、

 尚、ラズパイ用ACアダプタを挿したスイッチ付きコンセントでのON/OFFとは別にラズパイ用boot/reboot/shutdown物理ボタン付き。

 音声認識にJuliusを使った自作スマートスピーカーに伝言とメモの機能を実装するにあたり、マイクとスピーカーを専有してしまうOSSやALSAからPulseAudioに移行しました。

 ちなみに便利なのでラズパイだけでなく、PC/Debianにも自作スマートスピーカー機能を搭載しています。

 自ずとモニタ付きとなるPC版スマートスピーカーには、PC及びラズパイ双方のスマートスピーカー機能のデスクトップアプリとしてPyQt5/Qt Designerによる操作パネルも作成しました。

Juliusスマートスピーカーとサウンド

 今回は、先日、スクリプトベースで機能を確認できた音声メモと伝言メッセージが、スマートスピーカーに実装するとなぜかできないLinuxのサウンドシステム問題にハマりつつ、解決した話です。

 尚、パソコン(Debian 9 Stretch)版、ラズパイ(Raspbian Stretch)版共に動作することを確認しました。

Linuxの音関係はシンプルなようで複雑

 Linuxにおいてサウンドサーバは、OSS/Open Sound System、後にALSA/The Advanced Linux Sound Architectureが広く使われるようになりました。

 何れも、とても優れたサウンドサーバなのですが、使用していて困ることがあるとすれば、スピーカーやマイクを専有してしまう性質があり、この壁にぶつかった時でしょう。

 これを解決するかのようにOSSやALSAをベースに仮想デバイス化することで専有問題を解消、ネットワーク越しにも使えるPulseAudioが登場しました。

Juliusとサウンドサーバ

 Juliusを導入する際、そのまま./configure、makeするとOSSがサウンドサーバとして使われます。

 ただ、今回使用させて頂いたJulius 4.4では、./configureする際に[--with-mictype=]オプションを指定でき、OSS、ALSAばかりでなく、PulseAudioやこれって何?というもの含め、実に多くの選択肢があります。

 が、既にリリースされている最新版Julius 4.5については、ドキュメントjulius/julius/00readme-ja.txtconfigure.inを読む限り、configure時にマイク入力用のオプションを指定する必要はなくなった模様?もpulseauidoについては、選択肢になく、除外されてしまった?と思いきや、Audio InputJulius Optionsには、PulseAudioもあり、...当然、ある方が嬉しいものの、どっち?

 => [2021/10/01]
 Raspberry Pi 3 Model B+サブパソコンにもJuliusを入れてみるにあたり、先送りしていた最新にしてみようとJulius 4.6をチョイス、ごにょごにょした後、sudo make install/julius -versionしてみたら、4.5からのようですが、既にPulseAudioが標準になっていました。
(これに伴ってだと思いますが、[--with-mictype=]オプションもなくなったようで指定するとそんなのないよといった旨の軽い警告が表示されます。)
 ただし、そのベースとしてOSS/ALSAを使うので従前通り、マイクを使う準備USB接続マイクの確認と環境変数設定は必要。

 => [2022/06/27]
 システムディスクとしていたUSBメモリにおいてシステムがおかしくなり、イメージから仕込み直すにあたり、Julius 4.6を入れてみたら、今度は、デフォルトがalsaで[--with-mictype=]オプションが復活していました。

 とりあえず、今回は、1つ前のバージョン4.4を前提に話を進めます。

これまでのJulius自作スマートスピーカーとサウンドサーバ

 冒頭の通り、自身は、Debian GNU/Linuxパソコンとラズパイ/RaspbianにJuliusを使ったスマートスピーカー機能を入れています。

 サウンドサーバについては、何も考えずに初めて検証したパソコンの方はデフォルトのOSS、ラズパイ3B+の方は、OSS非対応の最新カーネルに対応すべく、ALSAとしていました。

 そんなラズパイスマートスピーカーはリビングで、パソコンスマートスピーカーはPC使用時に快適に使用しています。

サウンドデバイス専有問題に直面

 ここで本題ですが、音声メモ機能と伝言メッセージ機能は、当然のことながら、マイクとスピーカーを使います。

 が、OSSやALSAの何れかで直接サウンドデバイスを制御する場合には、スマートスピーカー(の音声操作と音声出力)が、これらマイクとスピーカーを専有してしまい、スマートスピーカーの一機能であるにも関わらず、これら機能で録音・再生しようにもできないという状況になりました。

 もう1つマイクを使うという手もなくもないものの、この問題の1つの解となるPulseAudioの存在は知っていたので取り入れてみることにしたのですが、一筋縄ではいきませんでした。

 それでも結果、JuliusスマートスピーカーでPulseAudioを使って伝言メッセージや音声メモ機能を利用できるようになった具体的な設定は次の通りです。

JuliusでPulseAudioを使う

$ cp path/to/julius path/to/bak/julius
$ cd path/to/julius
$ sudo apt install libpulse-dev
$ ./configure --with-mictype=pulseaudio
$ make clean
$ make
$ cp julius-kits/grammar-kit/bin/linux/mkgshmm mkgshmm/
$ sudo make install
$

 使用中だった為、既に展開してあったJulius一式を念の為、バックアップコピーしておきました。

 尚、PulseAudioを使うにあたり、Debianの場合、simple.hなるものが必要な関係でなければ、libpulse-devパッケージをインストールしておきます。

 Juliusのパスに移動し、./configureの--with-mictypeオプションにpulseaudioを指定、以前のmake状態を初期化するためにmake clean、改めてmake。

 ここでJuliusをインストールするためにjulius/mkgshmm/mkgshmmファイルが必要になります。

 が、ないはずなのでfindで探すなりしてと言いつつ、grammar-kitをダウンロードしてあればですが、Linuxの場合、path/to/julius/julius-kits/grammar-kit/bin/linux/mkgshmmがあるのでこれをjulius/mkgshmm/以下にコピーしておきます。

 grammar-kitをダウンロードしていない場合には、grammar-kitのgithubからmkgshmmだけをダウンロードすると良いでしょう。

 その後、pulseaudio対応したJuliusをmake installします。

 ちなみに、なぜか、julius/mkgshmm以下に配置するmkgshmmファイルは、makeだったか、make installだったかするたびに消えるので、もし、make、make installし直す際は、改めて用意することになると思います。

Juliusのマイク設定

$ cd path/to/julius/julius-kits/dictationkit/
$ cat config_file
-w mysmartspeaker.eucjp
-v model/lang_m/bccwj.60k.htkdic
-h model/phone_m/jnas-tri-3k16-gid.binhmm
-hlist model/phone_m/logicalTri
-n 5
-output 1
-input mic
-input pulseaudio
-rejectshort 600
-charconv euc-jp utf8
-lv 1500
$

 Juliusスマートスピーカーでは、dictationkitを使わせて頂いており、Julius実行時の構成ファイルに[-input oss]としていたところを[-input pulseaudio]に変更しておきました。

 尤も./configureの--with-mictypeオプションにpulseaudioを指定してあれば、[-input mic]だけで事足りるような記述もありますが、念の為。

ALSA構成ファイルの設定

$ cat /etc/asound.conf
pcm.pulse {
  type pulse
}
 
ctl.pulse {
  type pulse
}
 
pcm.!default {
  type pulse
}
ctl.!default {
  type pulse
}
$ cp /etc/asound.conf ~/.asoundrc
$

 自身が使わせて頂いているDebian Stretchでは、デフォルトのサウンドサーバは、ALSAです。(以前、敢えてOSSを使っていた時は、modpobeでsnd_pcm_ossを追加するなど別途作業が必要でした)。

 PulseAudioが入っていると基本、何もしなくてもALSAをベースに良きに計らってくれます。

 が、USBスピーカーやUSBマイクについては、PulseAudio音量調節パネルなどで「代替として設定」など手動操作が必要な場合があるものと思われ、スマートスピーカーの場合、ユーザーが画面に向かっているわけではない為、GUI操作するわけにはいきません。

 そこをPulseAudioとの間でうまいことやってもらうためにALSAの構成ファイル/etc/asound.conf、~/.asoundrc(共になければ作成)を使うことができます。

 実際には、このように/etc/asound.conf書いて~/.asoundrcとしてコピーします。

$ cat /proc/asound/modules
$ cat /etc/modprobe.d/alsa-base.conf
options snd slots=snd_usb_audio,snd_hda_intel
options snd_usb_audio index=0
options snd_hda_intel index=1
$

 また、前述のdefault.paでset-default-sourceを設定してあれば、必要はないとは思いますが、もし、うまくいかないようであれば、ALSAが認識するデバイス順を内蔵ではなく、USBデバイスが優先されるように変更してみるのも良いでしょう。

 これには、/etc/modprobe.d/alsa-base.conf(なければ作成)を使います。

 環境の確認が必要ですが、自身のノートPCではsnd_hda_intelだった部分は、Raspberry Piでは、現時点では、snd_bcm2835です。

 ここでマシンを再起動します。

 /etc/modprobe.d/alsa-base.confを作成・変更した場合、設定値は、/proc/asound/modulesが更新され、これに反映されます。

PulseAudio用コマンドpacmd/pactl

$ pacmd list-sources
$ pacmd set-default-source alsa_input.usb-Generic_USB2.0_PC_CAMERA-02.analog-mono
$ pacmd set-source-volume alsa_input.usb-Generic_USB2.0_PC_CAMERA-02.analog-mono 46000
$ pulseaudio -k
$

 PulseAudioには、pacmdやpactlなどのCLIコマンドがあります。

 ここまでのステップを踏んでいれば、pacmd list-sourcesとした時に対象となるUSBマイクがリストに挙がっているはずです。

 PulseAudioが認識しているマイク(source、ちなみにスピーカーはsink)のリストを見るとデフォルトにはindexの前にアスタリスクがあるのですが、他がデフォルトとなっていた為、pacmd set-default-sourceで使用するマイクをデフォルトに設定します。

 この時、指定しているマイクを指す値は、pacmd list-sources結果の[index]のすぐ下にある[name]値です。

 また、途中、Juliusスマートスピーカーでマイクをテストしてみたところ、PulseAudio音量調節パネル上のスライダが概ね70%以下が応答が良かったのでpacmd set-source-volumeで音量設定しておきました。

 helpを見ると何れもマイクは、index値かname値で良いようです。

 ただ、index値は、何かの折に変動することもあるように見受けられたのでname値としました。

 設定後は、pulseaudioを-k(必要なら手動でpulseaudio --start)として再起動します。

 音量は、比率(百分率)ではないのが意外でしたが、PulseAudio音量調節パネルを眺めつつ、ちょうどよくなるあたりの数字を当てました。

 が、時折、比率が、極々微妙に(1〜2%)変わっていることがあるような?

 尚、使っている内に、どうやらpacmdによる設定はpulseaudioの再起動後に有効になり、pactlでの設定は、リアルタイムで有効になるという違いに気づきました。

 ここでは、スマートスピーカー操作用に音量を事前に設定しておくため、pacmdを使いましたが、ここで変更したことにより、音声メモ、伝言メッセージのスクリプトでは、録音前後にpactlでマイクの入力音量変更を行なっています。

$ arecord test.wav
$ aplay test.wav
$

 尚、この時点でデバイス指定することなくarecordで指定したマイクから録音、これをaplayで再生することができるはずです。

PulseAudio構成ファイル

$ sudo vi /etc/pulse/default.pa
...
set-default-source alsa_input.usb-Generic_USB2.0_PC_CAMERA-02.analog-mono
...
$ cp /etc/pulse/default.pa ~/.config/pulse/
$

 PulseAudio構成ファイルは、/etc/pulse/以下にあり、今回の目的においては、この内、default.paの最終行にあるset-default-sourceを使ってマイクを設定しておき、一応、これをホームディレクトリの.config/pulse/以下にもコピーしておきます。

systemdサービスをユーザー起動に

$ cd /etc/systemd/system
$ sudo cp dhcpcd5.service mysmartspeaker.service
$ sudo vi mysmartspeaker.service
[Unit]
Description=My Smart Speaker service
Wants=network-online.target
After=network-online.target
 
[Service]
Type=oneshot
#ExecStart=/path/to/.mysmartspeaker_target.sh
ExecStart=/bin/su - USER /bin/sh -c "/path/to/.mysmartspeaker_target.sh"
RemainAfterExit=yes
 
[Install]
WantedBy=multi-user.target
$

 何れも良好であることを確認後、結果、従前、systemdでroot起動させていたJuliusと応答スクリプトをユーザー起動すべく、systemdサービスファイルを若干変更しました。

 というのもこれをroot起動させるとPulseAudioもroot起動でないといけないような雰囲気になり、PulseAudioには、system-wideモードとして--system[=BOOL]オプションもありますが、セキュリティ面の不安は残りますし、rootでJulius起動時に同時に起動させることもできますが、デバイスが占有されるようだった為です。

 個人のPC(ラズパイにしてもスマートスピーカー専用マシン)であり、マルチユーザーで使うことはないので十分です。

 systemdへの理解は、浅いので修正の余地もあるでしょうし、後述のように代替策をとったりしていますが、とりあえず、動いているのでよしとしています。

systemdサービスから呼ぶファイルの編集

$ cat .mysmartspeaker_target.sh
#!/bin/sh
 
find /var/log/ -type f -name \* -exec cp -f /dev/null {} \;
 
pkill -f voicerecieve.pl && \
pkill -f julius
 
julius -C /path/to/julius/julius-kits/dictation-kit-v4.4/mydebug.conf -C /path/to/julius/julius-kits/dictation-kit-v4.4/am-gmm.jconf -module &
 
sleep 10
 
/path/to/voicerecieve.pl &
 
pulseaudio -k
 
$

 ここまでやってみたところ、root起動からユーザー起動に変えたからか、systemctl restart mysmartspeaker.service時にJuliusコマンドと/path/to/voicerecieve.plのプロセスが、restartする度に増殖、多重起動する現象に遭遇しました。

 systemdでの対策を調べてみたのですが、難解過ぎるので読解を諦め、systemdサービスファイルからコールするファイル内でこれらをpkill -fする方法でしのぎました。

 PulseAudioを使う場合、環境変数ALSADEVやOSS用のAUDIODEVの設定は不要です。

 find行は、本来は不要であり、最近はこれを実行した理由となる現象には見舞われていないのすが、ある日突然、ログファイルが増殖する現象に遭遇した為、追記した名残です。

 念の為、期待するデバイスを割り当てるべく、Julius及び応答スクリプト起動後にpulseaudio -kしておきました(後は自動でデバイスを関連付けしてくれる模様)。

systemdサービスの有効化と開始

$ sudo systemctl stop mysmartspeaker.service
$ sudo systemctl disable mysmartspeaker.service
$ sudo systemctl daemon-reload
$ sudo systemctl enable mysmartspeaker.service
$ sudo systemctl start mysmartspeaker.service
$

 ここまで一通り、完了したら、systemdでスマートスピーカーサービスを起動します。

動作確認

$ arecord test.wav
$ aplay test.wav
$

 スマートスピーカーが機能しつつ、arecord/aplayでデバイス指定することなく、録音・再生ができれば、成功です。

備考

 作業中、ハマりどころ盛りだくさんでした。

 その一例は次の通りです。

ホーム前へ次へ