如何将 Docker 容器中的音频暴露给 Mac?

Posted

技术标签:

【中文标题】如何将 Docker 容器中的音频暴露给 Mac?【英文标题】:How to expose audio from Docker container to a Mac? 【发布时间】:2017-03-01 09:38:18 【问题描述】:

我知道在 Linux 主机系统上使用脉冲音频是可能的,但 paprefs 是为 linux 而不是为 mac 构建的。

【问题讨论】:

【参考方案1】:

Docker-for-Mac 虚拟机没有任何声音直通设备,因此您无法从这个角度利用任何东西。相比之下,virtualbox 或 vmware fusion VM 确实有能力做直通音频。

我能够使用以下命令安装 pulseaudio 并在 OSX 上工作:

brew install pulseaudio

我能够通过运行以下命令来验证这是否有效,并且听到了我的扬声器发出的声音:

paplay cockatiel.wav

我的下一步是找到具有paplay 副本的图像。我找到了jess/pulseaudio,它似乎打算作为一个pulseaudio 服务器,但我应该也可以将它用作一个客户端

我在 Archlinux Wiki 上找到了以下关于设置 pulseaudio 网络声音的指南:https://wiki.archlinux.org/index.php/PulseAudio/Examples#PulseAudio_over_network

通过执行以下操作,我能够使其适应这种情况。我在我的 Mac 上编辑了/usr/local/Cellar/pulseaudio/9.0/etc/pulse/default.pa,并取消了以下两行的注释:

load-module module-esound-protocol-tcp
load-module module-native-protocol-tcp

我在我的 Mac 上重新运行 paplay cockatiel.wav 以确保我的更改仍然有效。如果我打错了,pulseaudio 守护进程似乎会按需启动,并将其投诉传回paplay 以打印在我的屏幕上。我对 default.pa 的这些更改仍然有意见,所以我对我的更改没有破坏任何东西感到满意。

接下来,我在这样的容器中运行 pulseaudio 客户端:

docker run --rm -v $HOME:$HOME -w $HOME -it \
  -e PULSE_SERVER=192.168.10.23 \
  -e HOME=$HOME --entrypoint paplay \
  jess/pulseaudio $HOME/cockatiel.wav

它的作用是将我的本地主目录作为一个卷运行一个容器。这有两个目的。首先是我的 cockatiel.wav 位于 $HOME 内。第二个是因为客户端和服务器都需要拥有相同的~/.config/pulse/cookie 文件的副本(根据archlinux wiki 指南)。

PULSE_SERVER 环境变量是我的 OSX 主机的 en0 IP 地址,所以 paplay 知道要连接到什么。

HOME 环境变量是必需的,因此 paplay 可以找到相同的 ~/.config/pulse/cookie 文件。

我能够通过 pulseaudio 播放在我的 docker-for-mac 上运行的容器中的声音。

只要您让~/.config/pulse/cookie 文件出现在正确的位置,您就应该能够播放声音。您不必使用主机卷来完成此操作 - 您也可以执行“docker cp”,甚至可以将 COPY 放入映像中。

【讨论】:

运行 paplay piano2.wav $ paplay piano2.wav W: [] caps.c: 通常所有额外的功能现在都会被删除,但这是不可能的,因为 PulseAudio 是在没有功能的情况下构建的支持。连接失败:连接被拒绝 pa_context_connect() 失败:连接被拒绝 @valentin_nasta 您是否设法解决了在 Mac 上安装 PulseAudio 的问题? 使用当前的 PulseAudio 10.0,运行“pulseaudio --daemonize=false -v”似乎没有启动,之后得到“W: [] socket-util.c: IP_TOS failed: Invalid argument”添加两个 module-esound-protocol-tcp / module-native-protocol-tcp 行。【参考方案2】:

在 Mac 上安装PulseAudio:

brew install pulseaudio

运行守护进程:

pulseaudio --load=module-native-protocol-tcp --exit-idle-time=-1 --daemon

在您的 Docker 容器中:

    安装 PulseAudio,例如,apt-get install pulseaudio。 设置以下环境变量:ENV PULSE_SERVER=docker.for.mac.localhost

运行时,将~/.config/pulse 目录与容器共享以进行身份​​验证。

你可以运行一个测试看看它是否像这样工作:

docker run -it -e PULSE_SERVER=docker.for.mac.localhost -v ~/.config/pulse:/home/pulseaudio/.config/pulse --entrypoint speaker-test --rm jess/pulseaudio -c 2 -l 1 -t wav

【讨论】:

原来我在 OS X 可访问性设置中设置了立体声 -> 单声道。立体声效果很好。谢谢! 在最近发布的 Docker for Mac(和 Windows)中,他们将魔术主机名更改为 host.docker.internal,我建议将 -v 旧语法更改为较新的 --mount type=bind,source=~/.config/pulse,target=/home/pulseaudio/.config/pulse 以避免创建如果您尚未运行 brew install pulseaudio 并对其进行配置,则主机上的配置为 root > 谢谢。我花了一段时间才弄清楚为什么测试可以正常工作,但我自己的容器却没有:mount ("-v ~/.config/pulse:/home/pulseaudio/.config/pulse") 指向jess/pulseaudio 图像创建的“pulseaudio”用户的主目录。我不得不将挂载更改为指向我用户的主目录。 @dragon788 尝试使用您的安装建议引发错误(说它需要绝对路径)。我设法让它工作,奇怪的是扬声器测试没有产生任何输出

以上是关于如何将 Docker 容器中的音频暴露给 Mac?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以将 USB 设备暴露给 LXC/Docker 容器?

如何让不同的 Docker 容器相互通信而不将端口暴露给全世界

如何在没有端口映射的情况下将 docker 容器的 ip 和端口暴露给外部 docker 主机?

Postgres 9.1 的 Docker 容器未将端口 5432 暴露给主机

Docker 和 netstat:netstat 不显示端口,由 docker 容器暴露

Gitlab CI runner 无法暴露嵌套 Docker 容器的端口