わふぅ。

わふです。

Raspberry Pi で動いている Docker の中から PulseAudio 経由で音を鳴らす

環境

たぶんホストが Arch Linux ARM ではなくても pacmanapt-get に変わるとかそれぐらいだと思います。 コンテナも ARM 版 Ubuntu である必要はないはずです。保証はしませんが……。

ホストの設定

PulseAudio のインストール

pacman 経由で PulseAudio をインストールします。

pulseaudio --start で PulseAudio のデーモンが立ち上がり、 /run/user/$uid/pulse/native というファイルができます ($uid はデーモンを起動したユーザーのユーザー ID です)。 このファイルは Unix ドメインソケットになっていて、ここにデータを書き込むことで音声を再生できるようになります。 また、pulseaudio --kill でデーモンを終了させることができます。

基本的にソケットファイルはデーモンが動いている間だけ存在しますが、 systemd のソケットアクティベーションという機能を使うと、 /run/user/$uid/pulse/native にアクセスがあった場合に自動で PulseAudio を立ち上げることができるらしいです。 systemctl --user start pulseaudio.socket でこの機能を有効化できて、 systemctl --user enable pulseaudio.socket でこの機能を永続化できます。

クッキーの設定

デフォルトでは /run/user/$uid/pulse/native への書き込みの際にクッキー (?) を用いた認証機能がついています。 この認証によって、音声を再生するためにはソケット (/run/user/$uid/pulse/native) への書き込み権限のほかに、 クッキー (/home/$user/.config/pulse/cookie) の読み込み権限が必要になります (/home/$user はデーモンを立ち上げたユーザーのホームディレクトリです)。

/etc/pulse/default.pa をいじることで、この機能を無効にできます。 load-module module-native-protocol-unix という行を load-module module-native-protocol-unix auth-anonymous=1 に変更することで達成できます。

認証が有効なままでもクッキーをコンテナへとマウントしてしまえばほとんど問題はないので、 以降は無効化しないときの設定方法を記述します。 無効化すると以降の記述で /home/$user/.config/pulse/cookie および $SERVER_COOKIE に関する 設定をスキップできます。

コンテナの設定

ソケット・クッキーのマウント

docker run でコンテナを作成するわけですが、 その際に以下の 2 つを -v オプションなどを使ってコンテナ内部にマウントします。

  • /run/user/$uid/pulse/native
  • /home/$user/.config/pulse/cookie

$user$uid は適切なものに置き換えておいてください。 また、マウントしようとしているファイルがきちんと存在することも確認してください。

環境変数の設定

以下の環境変数をコンテナ内で設定します。

  • PULSE_SERVER=unix:/path/to/native
  • PULSE_COOKIE=/path/to/cookie

/path/to/native および /path/to/cookie はそれぞれ /run/user/$uid/pulse/native/home/$user/.config/pulse/cookie のマウント先のパスを指定してください。

PulseAudio のインストール

apt-get install pulseaudio するだけです。

こうすることで、コンテナ内のプログラムたちは PulseAudio を通じてホスト側に音声を送ることが可能になります。

[ユーザープログラム] → [PulseAudio in Docker] → [Unix ドメインソケット] → [PulseAudio in Host] → [スピーカーなど]

おそらくこういう経路で音声が送られるはずです。

mpg321

音声を再生するプログラムとして今回は mpg321 を使います。 apt-get 経由でコンテナ内にインストールしてください。 あとは設定がうまくいっていれば mpg321 test.mp3 で音声が再生できていると思います。

デフォルト設定では mpg321 は ALSA を使って音声を再生しようとします。 これはコンテナ側の Ubuntu では (たぶん apt-get install pulseaudio のときに ALSA から PulseAudio へのリダイレクトが自動で設定されるので) 問題ないですが、ホスト側の Arch Linux で mpg321 を用いて音声の同時再生をしようとすると問題になります。

ホスト側では /etc/libao.conf の中身をすべて削除して default_driver=pulse と書くことで解決できます。 pulseaudio-alsa パッケージをインストールして ALSA から PulseAudio へのリダイレクトを設定すると解決するのかもしれませんが、そちらの解決方法はよくわからなかったのでやめました。

参考資料

感想

Ubuntu と Arch Linux でいろいろ違うから困る (それはそう)。