如何让 pulseaudio 同时在 KVM 虚拟机(以 root 身份运行)和桌面应用程序(不以 root 身份运行)中播放声音?
看来默认情况下,它每次只会为一个用户播放声音,而阻止所有其他用户。
例如,
我播放一些音乐:
mplayer ~/Music/*
我的虚拟机启动如下:
kdesu qemu-system-x86_64 -enable-kvm [... disks, network, etc. ...] -soundhw hda
这将以 root 身份运行该进程,并使用运行该进程的用户的 X 显示器。直到 mplayer 停止,声音才会起作用。
如果在 root shell 中运行,我会得到:
pulseaudio: pa_context_connect() failed
pulseaudio: Reason: Connection refused
pulseaudio: Failed to initialize PA contextaudio: Could not init `pa' audio driver
ALSA lib pcm_dmix.c:1018:(snd_pcm_dmix_open) unable to open slave
alsa: Could not initialize DAC
alsa: Failed to open `default':
alsa: Reason: Device or resource busy
ALSA lib pcm_dmix.c:1018:(snd_pcm_dmix_open) unable to open slave
alsa: Could not initialize DAC
alsa: Failed to open `default':
alsa: Reason: Device or resource busy
audio: Failed to create voice `dac'
然后虚拟机运行并且它的声音设备看起来可以工作,但没有播放声音。
然后我可以停止 mplayer,然后就可以从 VM 播放声音而无需重新启动它。
然后,如果我再次启动 mplayer,我会出现错误并且没有声音:
AO: [pulse] 44100Hz 2ch s16le (2 bytes per sample)
Video: no video
Starting playback...
A: -0.0 (unknown) of 308.2 (05:08.2) ??,?%
Audio device got stuck!
A: -0.0 (unknown) of 308.2 (05:08.2) ??,?%
Audio device got stuck!
A: -0.0 (unknown) of 308.2 (05:08.2) ??,?%
Audio device got stuck!
A: -0.0 (unknown) of 308.2 (05:08.2) ??,?%
我相信我可以通过卸载 pulseaudio 并改用 ALSA 来解决这个问题,但之后我需要重新配置 qemu 配置并从源代码构建它。我想通过配置 pulseaudio 来做到这一点,就像在 ALSA 中使用软件混音器一样。
答案1
您可能已经正确设置了 Qemu 的环境变量,例如:
QEMU_AUDIO_DRV=pa
但是在设置 QEMU_PA_SINK 之前,必须安装包,paprefs
该包包含 pulseaudio 的类似服务器的设置。
我已经检查了 PulseAudio 偏好设置中的所有内容,但可能只是选项:
- “启用本地声音设备的网络访问”,
- “允许局域网上的其他机器发现本地声音设备”和
- “不需要身份验证”
重新启动 pulseaudio 后,combined
源可用。然后以您的用户身份启动:
pulseaudio -k
pactl list short sinks
如果您看到源名称,combined
您可以继续为 Qemu 设置其他环境变量,例如:
QEMU_PA_SINK=combined
QEMU_PA_SOURCE=input
最后一步,重新启动虚拟机
https://wiki.archlinux.org/index.php/QEMU <- 参见音频部分 https://freedesktop.org/software/pulseaudio/paprefs/
编辑:现在我们有 QEMU 版本 4.0
https://www.redhat.com/archives/libvir-list/2019-February/msg01305.html
那么虚拟机 xml 定义中的常见更改如下
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
...
<qemu:commandline>
<qemu:arg value='-audiodev'/>
<qemu:arg value='pa,id=pa1,out.name=combined,in.name=input'/>
</qemu:commandline>
</domain>