背景
Dockerで音を鳴らそうとしたら以下のようなErrorが出た時のお話
ALSA lib pulse.c:243:(pulse_connect) PulseAudio: Unable to connect: Protocol error
Playback open error: -111,Connection refused
ALSA lib pcm_dmix.c:1052:(snd_pcm_dmix_open) unable to open slave
aplay: main:788: audio open error: Device or resource busy
ここではaplayを使って音を出そうとしてるよ
必要な知識
ALSA と PluseAudio の関係
歴史的な理由からか、Linux の音声入出力は PulseAudio と ALSA の二階建てになっている。ALSA は個々のサウンドカードを担当するのだが、一つのサウンドカードには一つのアプリしかアクセス出来ない。複数のアプリの音声入出力を調停するのは PulseAudio が担当している。具体的には、次のようになっている。
ALSA は色んなサウンドカードを統一的に操作出来るようにする仕組み。
アプリは直接 ALSA を操作しなくても良い。
あるアプリが ASLA 経由でサウンドカードを操作している間、他のアプリからそのサウンドカードを使えない。
とはいえ、直接 ALSA を使って音声入出力を行うアプリが存在する。
PluseAudio は複数のアプリが同時に同時にサウンドカードを使う仕組み。
お行儀の良いアプリは ALSA ではなく、PulseAudio 経由で音声入出力を行う。
とはいえ、直接 ASLA を使ってしまうアプリのために仮想サウンドカードの仕組みがある。
お行儀の良いアプリは PulseAudio 経由で音声入出力を行う事を期待しているが、ALSA を直接使ってしまうアプリのために PulseAudio は仮想サウンドカードとしても動作する。
ASLA から見ると、PulseAudio は default サウンドカードとして動作する。
アプリが default サウンドカードを通して再生を行うと、実際には PulseAudio がミキシングしてデフォルトのサウンドカードに音をだす。
テストの仕方
コンテナ内で,
サンプルデータのダウンロード
$ wget http://freewavesamples.com/files/Kurzweil-K2000-Dual-Bass-C1.wav
サンプルデータの再生
aplay Kurzweil-K2000-Dual-Bass-C1.wav
aplay -l
とか aplay -L
でサウンドデバイスを確認できるよ.
aplay
はapt install alsa-utils
で入れられるよ.
ただし,今回はno soundcards foundでおっけーだよ
Dockerfileの設定
apt install pulseaudio
を入れておく.
DockerをRunするときの設定
準備
pulseaudio.socket ってファイルを生成する
ホスト側で
$ pacmd load-module module-native-protocol-unix socket=/tmp/pulseaudio.socket
すると/tmp
に生成される.
pulseaudio.client.conf ってファイルを作る
/tmp
にpulseaudio.client.conf
って名前のファイルを作る
つまり下記の通り
$ touch /tmp/pulseaudio.client.conf
そのファイルをテキストエディタやらで開いて,下記を書き込む
default-server = unix:/tmp/pulseaudio.socket
# Prevent a server running in the container
autospawn = no
daemon-binary = /bin/true
# Prevent the use of shared memory
enable-shm = false
OptionsをつけてRunする
$ docker run --rm \
--env PULSE_SERVER=unix:/tmp/pulseaudio.socket \
--env PULSE_COOKIE=/tmp/pulseaudio.cookie \
--volume /tmp/pulseaudio.socket:/tmp/pulseaudio.socket \
--volume /tmp/pulseaudio.client.conf:/etc/pulse/client.conf \
--user $(id -u):$(id -g) \
imagename
結論
$ aplay Kurzweil-K2000-Dual-Bass-C1.wav
してドゥーンってなれば成功です.