音楽サーバー(mpd) から AirPlay スピーカーを鳴らす

Ubuntu Server 14.04 をインストールして動画サーバーにしている HP Proliant MicroServer N54L に音楽サーバーの機能を追加してみようと思いました。やりたいこと(条件)は、

  • サーバーはよくON/OFFするので起動/シャットダウンは速くしたい。そのため、X はインストールしたくない
  • 同じ理由で、ログオンしない状態で音楽サーバーとして機能するようにしたい
  • 家にある 2 台の AirPlay デバイス(AirMac Express と Pioneer XW-SMA3)にストリーミングして再生したい
  • 手持ちの iPhone から曲の選択等、コントロールしたい
  • 再生した曲は Last.fm に Scrobble したい
  • 曲は OSX 上の iTunes にためてある。この曲データを(rsync等で)フォルダーごとサーバーにコピーするだけで再生対象になるようにしたい

という感じです。色々調べた結果、以下のソフトウェアで実現できそうだということがわかりました。

  • mpd
  • mpdscribble
  • PulseAudio と、そのプラグイン raop モジュール
  • MPoD (iOS アプリケーション)

自分なりに理解したのは、

  • mpd は iTunes みたいなもの(ただし、GUIは無いサーバープログラム)。音楽サーバーの中心となるプログラム。
  • MPoD は mpd のクライアントである。
  • mpd で再生した場合、音の出力先には PulseAudio を選択できる
  • PulseAudio には色々なモジュールを組み込めるが、raop モジュールを組み込むと、AirPlay デバイスにストリーミングできる
  • mpdscribble もサーバープログラム。mpd で再生している曲を調べ、Last.fm に Scrobble してくれる

しかし、慣れていないこともあって色々な所でつまづいてしまい、構築に結構時間がかかってしまいました。特につまづいた箇所は、以下の2点でした。

raop モジュール

Ubuntu Server 14.04 では PulseAudio と raop モジュールは両方とも apt-get で簡単にインストールできます。ところが、再生してみるとブチブチ音が途切れてまともに再生できません。raop2 モジュールというのがあるようなので、それを試してみたところうまくいきました。

PulseAudio の System Mode

PulseAudio はログオンしたユーザーの権限で起動させるのが基本のようで、ウェブ上の解説記事もそれに沿ったものが多く見つかります。上に書いたようにログオンしない状態で動作させたいので迷ったのですが、System Mode という動作方法を試してみるとうまくいきました。System Mode は、

WhatIsWrongWithSystemWide

に書かれているようにセキュリティ上問題があったり、一部の機能が使えなかったりするようですが他に良い方法も思いつかなかったのでとりあえず良しとします。

手順

せっかくうまくいったので手順をまとめておきます。

PulseAudio (raop2) のインストール

開発元のサイト Pulseaudio-raop2 の手順通りにビルドします。

$ sudo apt-get update
$ sudo apt-get install build-essential paprefs git pulseaudio-module-raop intltool
$ sudo apt-get build-dep pulseaudio
$ git clone https://github.com/hfujita/pulseaudio-raop2.git
$ cd pulseaudio-raop2
$ ./autogen.sh
$ CFLAGS="-ggdb3 -O0" LDFLAGS="-ggdb3" ./configure
$ make

この後リンク先の手順では動作確認をするのですが、ここではそのままインストールしてしまいます。

$ sudo make install

/usr/local 以下にインストールされます。

$ pulseaudio --start

と実行してみると、

pulseaudio: error while loading shared libraries: libpulsecore-5.99.so: cannot open shared object file: No such file or directory

というエラーが出たので、

$ sudo ldconfig

を実行して共有ライブラリの依存関係情報を更新してやります。次に、/usr/local/etc/pulse/default.pa と、/usr/local/etc/pulse/system.pa の末尾に以下の行を追加します。

load-module module-raop-discover

default.pa は通常のモードで起動した時の設定ファイル、system.pa は System Mode で起動した時の設定ファイルとのことです。一度通常のモードで起動させ、AirPlay デバイスに接続できるか確認するとともに AirPlay デバイスの名前を確認します。もちろんこの時点で AirPlay デバイスは電源を入れておく必要があります。

$ pulseaudio --start
$ pacmd list-sinks | grep name:
        name: <alsa_output.pci-0000_00_1f.4.analog-stereo>
        name: <raop_output.Base-Station-xxxxxx.local>
        name: <raop_output.XW-SMA3-xxxxxx.local>

raop_output という文字列が含まれる行が AirPlay デバイスを表します。ここでは2台(AirMac Express と Pioneer XW-SMA3)見つかっています。<> で囲まれた文字列は後で mpd の設定に使うので記録しておきます。

次に、今ビルドした(/usr/local/bin にある) pulseaudio を System Mode で動作させるために /etc/init/pulseaudio.conf を以下のように編集します。

start on runlevel [2345]         <---- コメントアウトを解除

exec /usr/local/bin/pulseaudio --system --daemonize --high-priority --log-target=syslog --disallow-exit --disallow-module-loading=$DISALLOW_MODULE_LOADING $PULSEAUDIO_ARGS    <--- /usr/bin/pulseaudio を /usr/local/bin/pulseaudio に修正

また、System Mode では autospawn 機能(PulseAudio のクライアントプログラムが必要に応じて PulseAudio を起動させる機能)は不要なので無効にするため、/usr/local/etc/pulse/client.conf に以下の行を追加します。

autospawn = no

いったんここで再起動します。

$ sudo shutdown -r now

起動後、動作しているか確認します。

$ ps aux | grep pulse

残念ながら起動していませんでした。/var/log/syslog を確認すると

Feb 28 13:08:37 pubuntu pulseaudio[1158]: [pulseaudio] core-util.c: Failed to create secure directory (/usr/local/var/lib/pulse): Permission denied

というエラーが出ていました。

$ ls -l /usr/local/var
合計 8
drwx------ 3 root root 4096  2月 28 13:08 lib
drwxr-xr-x 3 root root 4096  2月 28 13:08 run

ということで、/usr/local/var/lib には root 以外はアクセスできないようになっていました。正しい対応であるかはわかりませんが

$ sudo chmod 755 /usr/local/var/lib

と root 以外でもアクセス可能にしました。もう一度再起動して確認してみます。

$ ps aux | grep pulse
pulse     1071  0.0  0.1 200944  3768 ?        S<l  17:23   0:00 /usr/local/bin/pulseaudio --system --daemonize --high-priority --log-target=syslog --disallow-exit --disallow-module-loading=1

今度はうまく行ったようです。

mpd のインストール
$ sudo apt-get install mpd

/etc/mpd.conf を編集し、一部の設定を変更します。

bind_to_address         "0.0.0.0"   <--- 任意のネットワークインターフェースでの接続を有効にします

audio_output {
        type            "pulse"
        name            "AirMac Express"
        sink            "raop_output.Base-Station-xxxxxx.local"
}

audio_output {
        type            "pulse"
        name            "Pioneer XW-SMA3"
        sink            "raop_output.XW-SMA3-xxxxxx.local"
}

/var/lib/mpd/music に何か音楽ファイルをコピーして mpd のデータベースをアップデートし、mpd クライアントである ncmpcpp で再生してみます。

$ sudo apt-get install mpc ncmpcpp
$ sudo cp Sally.m4a /var/lib/mpd/music
$ mpc update
$ ncmpcpp

Sally.m4a を再生してみましたが、すぐに Pause 状態になってしまいうまく行きません。/var/log/mpd/mpd.log を調べました。

Feb 28 18:47 : pulse_output: Failed to open "AirMac Express" [pulse]: failed to connect: Access denied

PulseAudio からアクセスが拒否されているようです。PulseAudio - Music Player Daemon Community Wiki を参考に以下を実行しました。

$ sudo usermod -aG pulse,pulse-access mpd

もう一度 ncmpcpp で再生しましたがやはり再生できません。/var/log/mpd/mpd.log のエラーメッセージは次の通り。

Feb 28 19:03 : pulse_output: "AirMac Express" [pulse] failed to play: failed to connect the stream: No such entity

"entity" というのは、音声の出力先(mpd.conf で、audio_output として定義したもの)を指していると思います。おそらく PulseAudio の raop モジュールが正しくロードできていないのではないかと推測しました。で、もしかしてと思い /etc/init/pulseaudio.conf を以下のように編集しました。

env DISALLOW_MODULE_LOADING=0      <--- 1 を 0 に変更

この状態で OS を再起動したところ、ncmpcpp で再生に成功しました! なお、PulseAudio が AirPlay デバイスと接続できているかは以下のコマンドで確認できます。

$ sudo -u pulse pactl list short | grep module-raop-sink

これで "raop_output.Base-Station-xxxxxx.local" のような文字列が出力されれば OK です。なお、PulseAudio を System Mode で動作させているときは、上記の通り pulse ユーザーで pactl コマンドを実行する必要があります。また、pactl と似たような機能を持つ(違いがよくわからない) pacmd というコマンドもありますが、こちらは pulse ユーザーでも実行できませんでした。

MPoD のインストール

普通に App Store からインストールします。"Connections" メニューから今設定した mpd サーバーに接続します。"DISCOVERED PLAYERS" に表示されたものを選ぶか、"Add player manually" を選択して IP アドレスを入力します。接続後、曲が再生できるか確認します。

mpdscribble のインストール
sudo apt-get install mpdscribble

自動起動させるために /etc/default/mpdscribble を編集。

MPD_SYSTEMWIDE=1       <---- 0 を 1 に変更

Last.fm への接続情報を /etc/mpdscribble.conf に設定。

[last.fm]
url = http://post.audioscrobbler.com/
username = foo     <--- ユーザー名を設定
password = bar     <--- パスワードを設定

これでようやく最初に書いた条件がクリア出来ました。

参考にしたサイト

raspbian - Redirect audio to another AirPlay device - Raspberry Pi Stack Exchange

MPD INSTALL USER SERVICE UBUNTU - Gnome Music Player Client

PulseAudio - Music Player Daemon Community Wiki