大坂なおみちゃん全豪オープン決勝進出を祝して!?Raspberry Pi 3 Model B+とJulius、Open JTalkベースの自作スマートスピーカーにUPnP/DLNAメディア再生機能を追加してみた話。
既存の主な機能は、
尚、ラズパイ用ACアダプタを挿したスイッチ付きコンセントでのON/OFFとは別にラズパイ用boot/reboot/shutdown物理ボタン付き。
今回は、これにMediaTombやMiniDLNA/ReadyMediaといったUPnP/DLNAメディア再生機能を追加する。
約3年運用しているRaspberry Pi 2 Model B/Raspbianサーバには、最初から、これらUPnP、DLNAメディアサーバも入れてあった。
今回は、これを自作スマートスピーカーから呼び出して再生するだけ。
とりあえず、ネット検索してみたところ、mplayerでUPnP/DLNAサーバ上のメディアってどうやって再生するんだ?など、直接再生しようとしてか、妙に難しく考えているっぽく、解決に至っていないケースが多いように見受けられた。
簡単にできるでしょと考えていた自身も一瞬、その渦に巻き込まれそうになり、以前、PC上のDebian 8 JessieやFedora 23、NetBSD 7.0、SHARP AQUOS TVで検証した記事を見直したりしてUPnP/DLNAクライアントとして使えたRythmboxでも使わないとダメか?なんてハマりかけたが、よく考えたら簡単でmplayerで実現できた。
簡潔に言うとマウントしてから、MPlayerにファイルパスを渡すだけ。
つまり、先のラズパイ上のNAS・ファイルサーバはSambaで実装してあり、アクセスするマシンからは、当該共有パスをマウント、mplayerにそこから辿った音源ファイルのあるパスを渡すだけでOK。
音源パスに[*](階層に合わせてpath/to/*/*など複数も可)を使えば、ディレクトリをプレイリストのように扱うことができるため、音源ファイルを直接指定する必要はなく、スマートスピーカーには好都合。
よってコマンドライン(CLI/CUI)操作もできるし、スクリプトに書くこともできる。
尚、今回は、映像は考慮せず、音源再生のみにフォーカスした。
UPnP/DLNAサーバは自前のサーバであり、例えば、手持ちの音楽CDをリッピングしてできた音源ファイルをアップしておけば、クライアントから再生することができる。
ということは、有線はもちろん、無線LANや無線アクセスポイントなど同じネットワーク内にいるパソコン、タブレット、スマホなどからもオリジナルの音源ライブラリを再生できることを意味する。
もちろん、メディアサーバには、後から追加することもできる。
市販の一部のスマートスピーカーにもこうした機能はある(全てのスマートスピーカーが対応しているわけではない)らしいし、今回は、そんなオリジナル音楽ファイル再生機能を自作スマートスピーカーに搭載、音声で再生、停止できるようにしたわけだ。
NetBSD上のSamba共有パスにWindows/Fedora/NetBSDからアクセスにも書いたが、Linuxからなら、Samba共有のマウントは、このようにすればよい。
リンク先にある通り、予め必要なパッケージもあるが、既にSambaサーバが稼働しているのであれば、それらはあるはず。
ただ、リンク先では、NetBSDでサーバを立てたこともあり、smbpasswdを使ったが、ある時点からpdbeditに切り替わったようだ。
自身は、この仕様変更に伴うものではないはずだが、ここで少しハマった。
なぜか、/etc/samba/smb.confに追記したユーザーとpdbedit -Lで出力されたユーザー一覧の結果があっていない。
実際には、sambaがユーザーとして存在すると思っていたら、存在せず、mountオプションで[-o username=samba]としていたことで権限がないだの、そんなパスはないだのと無駄にアクセスできずに時間をとられた。
マウントさえしてしまえば、あとは、MPlayerにファイルパスを渡すだけだ。
前述の通り、アスタリスクで抽象化でき、プレイリストのように振る舞ってくれるのがありがたい。
尚、ファイルパスにスペースがあるとエラーになるシーンもあるが、これは大丈夫だった。
自作スマートスピーカーの音声認識ソフトウェアJuliusの独自辞書に今回のオリジナル音源再生時の呼びかけ情報を追加し、eucjpに変換しておく。
今回は、「音楽かけて」と呼びかけた時、Juliusが「音楽再生」と認識、テキスト出力したものを自作スクリプト./voicerecieve.plの条件分岐でこれに該当した場合、音声メッセージ「CDライブラリを再生します」に続き、手持ちの複数のCDからリッピング、ラズパイ/DLNAサーバ上にアップしてあるオリジナルミュージックライブラリが再生されるようにした。
Juliusの音声テキスト変換出力結果を受ける自作スマートスピーカー用スクリプト./voicerecieve.plは、このように編集した。
メディアサーバ上の音源を再生する際には、my_music.shを呼び、これまで個別にpkillしていたコマンドをstop_radio.shにまとめることにした。
stop_radio.shにまとめたのは、音源混線回避にあたり、スクリプトをよりスマートにするため。
というのもラジオと天気予報や日付時刻などは再生が被っても、むしろ都合がよいこともあるが、複数のラジオが再生され、混線する可能性があり、そうなると何とも気色悪い響きになることがあったのだが、わかっていつつも面倒で対策は先延ばしにしていた。
今回、mplayerによる再生のみならず、メディアサーバパスをマウントしており、再生を停止する際には、DLNAメディア(ラズパイ)サーバを常時起動していない関係でアンマウントもしておきたい、となるとラジオ停止時の処理に追加することになるので、この機会にスクリプト化することにした次第。
ラジオや音源再生の条件分岐全て最初にこのスクリプト行を追加しておけば、pkillしてから再生するため、誤動作による混線を回避できる。
音源再生スクリプトmy_music.shは、こんな感じにしてみた。
mountは、通常、root権限が要るが、systemd(デーモン)のサービスファイル内でsuしない限り、Juliusも自作スクリプトもroot起動するため、スクリプト上でsudoを付ける必要はない。
[man mount.cifs]にあるようにcifsの場合、mountオプション-oのusername/passwordを直接書く代わりにファイルに書いておくこともできる。
[credentials=/home/xxx/.smb_credencials]などとして置き換え、[/home/xxx/.smb_credencials]ファイルに[username=XXX]行、[password=YYY]行、必要なら加えて[domain=WORKGROUP_NAME]を1行ずつ書いて[chown 0600 /home/xxx/.smb_credencials]しておけばよい。
Linux(やWindows)では、Avahi、macOSでは、Bonjourをインストール済みであれば、mDNSでホスト名.localを使え、ここでもこれを指定することができる。
Samba共有のマウントポイント配下のパスが通れば(0/true)、「CDコレクションを再生します」、パスが通らなければ(1以上/false)、mount失敗ということで「サーバーがマウントされていません」とメッセージが再生されつつ、端末から実行した場合「NAS Mount Error」とエラーメッセージがテキスト出力される。
一瞬、毎回同じ再生順じゃな...シャッフル再生か、どう実装するか...と思ったが、なんのことはないman mplayerを見たら、あるじゃんshuffleオプション、mplayerすごし。
尚、自身は、今のところ、ラズパイサーバを常時起動しておらず、必要都度起動(要らない時はシャットダウン)している為、mountチェックを入れている。
音源再生スクリプトstop_radio.shは、こんな感じにしてみた。
もはや、rtmpdumpについては不要だが、一応、rtmpdumpとmplayerをpkill、マウントポイント/mnt/nasをumount。
umount -f /mnt/nasをバッククォートで括ってダミーの変数に入れたあと、$?で評価する手もあるが、今のところ、これで支障はない。
構成ファイル変更の反映については、systemd/systemctlならsystemd自動起動設定参照。
ユーザー権限でmount/umountさせないとと思い/etc/fstabにNASをnoautoでマウント、再起動。
mount -aしておけば、再起動する必要はないと思ったが、一応。
/etc/fstabでも前述のようにusername/passwordに代えて、これらを書いたファイルを指定すべく、[credentials=/home/xxx/.smb_credencials]を使うこともできる。
前述の通り、Linux(Windows)では、Avahi、macOSでは、Bonjourをインストール済みであれば、mDNSでホスト名.localを使えるわけだが、/etc/fstabでもこれを指定することができた。
が、よく考えたら、systemdでデーモン化しており、.serviceファイルでは、現状、Juliusも自作スクリプトもsuしておらず、root起動となるため、一般アカウントでマウント・アンマウントさせる必要なかったか...と思いきや、なぜか、必要っぽい...。
また、ちゃんと精査していないが、この場合、mountオプションには、どうもuserとusers両方とも必要な模様。
man mountによれば、userは、一般ユーザーでもmountできる指定だが、当該マウントポイントはmountしたユーザーしかumountできない一方、usersは、他のユーザーでもumountできるとあり、/etc/fstabへの追記が必要だとしてもusersだけで事足りそうなのだが...。
ラズパイとPCのスマートスピーカー両方やってたら、ちょっと混乱してきた...、systemdの.serviceファイルでsuでもしない限り、やはり、/etc/fstabの設定は要らないかも...。
何れにしてもラズパイスマートスピーカーもPC/Debianに搭載したスマートスピーカーもうまいこと機能している。