跳转到内容

PipeWire/故障排除

来自 Arch Linux 中文维基

继续之前,请先检查以下最基本的事项:

  1. 是否选择了正确的声卡?
  2. 软件和硬件音量是否已调高?
  3. 线缆是否连接到了正确的端口?
  4. USB 声卡是否直接连接到计算机?
  5. 是否已调高麦克风音量、连接麦克风并开启 XLR 幻象供电?
  6. 环绕声是否异常?如果是,首先尝试卸载 UCM 配置软件包 alsa-ucm-conf包。参见 PulseAudio/Examples#Disabling UCM/"HiFi"。
  7. 重启 pipewire.service 和 pipewire-pulse.service 用户单元。

音量

多种应用程序没有声音,但浏览器有声音

本文或本章节的事实准确性存在争议。

原因: 问题的根本原因仅为猜测,尚未得到验证。是否只是应用程序被静音?(在 Talk:PipeWire/故障排除 中讨论)


使用 mpv 检查已安装的编解码器是否正常工作:

$ mpv --ao=alsa test_file.mpv
$ mpv --ao=pcm test_file.mpv
$ mpv --ao=jack test_file.mpv
$ mpv --ao=pulse test_file.mpv
$ mpv --ao=openal test_file.mpv

如果上述部分或全部测试能够发出声音,而以下命令不能:

$ mpv --ao=pipewire test_file.mpv

则可能是 pipewire 通道被静音。安装并运行 pavucontrol。

在“配置”选项卡中选择适当的设备,然后在“输出设备”选项卡中再次选中它。在播放 mpv --ao=pipewire test.mp4 视频的同时,使用“静音”按钮先静音再取消静音。

或者删除 ~/.local/state/wireplumber/,再通过 systemctl --user restart pipewire pipewire-pulse wireplumber.service 重启 PipeWire。

音量过低

将 PulseAudio 替换为 PipeWire 后,声音可能起初正常,但重启后音量变得低得难以接受。

打开 alsamixer,按 F6 选择正确的声卡,并确保 ALSA 音量为 100%。alsactl 应在重启后保留此设置。

SDDM 和 LightDM 用户登录后设备音量未恢复

如果使用 SDDM 或 LightDM,并发现登录后音量未正确恢复,可以屏蔽显示管理器用户的 PipeWire,因为显示管理器账户下运行的 WirePlumber 可能干扰当前用户的 WirePlumber 会话。

# systemctl --user -M user@ mask pipewire.socket

对于 SDDM,将 user 替换为 sddm;对于 LightDM,则替换为 lightdm。

更多详细信息参见Debian Wiki 文章。

麦克风

PipeWire 无法检测麦克风

如果使用笔记本内置麦克风,或通过耳机插孔连接的麦克风,首先确保当前使用的配置文件已启用模拟输入。可以在 pavucontrol包 中(也可能在桌面环境的声音设置中)查看。在 pavucontrol 的“配置”选项卡中,确保“内置音频”(或类似名称)选择了“模拟立体声双工”。如果使用 5.1 声道、HDMI 音频等高级音频配置,请选择包含“+ 模拟立体声输入”的配置文件。

PipeWire 的 alsa-monitor 模块默认使用 alsa-card-profiles包 检测设备。如果无法正常工作,尝试禁用 api.alsa.use-acp,或者在 wireplumber包 中启用 api.alsa.use-ucm:

/etc/wireplumber/wireplumber.conf.d/alsa-config.conf (or ~/.config/wireplumber/wireplumber.conf.d/alsa-config.conf)
monitor.alsa.properties = {
  # 使用 ALSA-Card-Profile 设备。它们通过 UCM 或 profile
  # 配置来设置设备和混音器参数。
  # alsa.use-acp = true
  # 如果可用,使用 UCM 代替 profile。也可以禁用此项,
  # 以跳过使用 UCM 配置文件的尝试。
  alsa.use-ucm = true
}

使用 pipewire-media-session包 时:

/etc/pipewire/media-session.d/alsa-monitor.conf (or ~/.config/pipewire/media-session.d/alsa-monitor.conf)
...
rules = [
    {
        ...
        actions = {
        update-props = {
            ...
            api.alsa.use-acp = false
...

随后重启 WirePlumber 并检查可用设备:

本文或本节内容已经过时。

原因: 新版本 pw-record 已不再提供 --list-targets 选项;请改用 wpctl status、pw-cli ls 或 pw-dump 列出对象。 (在Talk:PipeWire/故障排除讨论)
$ pw-record --list-targets
Available targets ("*" denotes default): 62
	58: description="Built-in Audio" prio=1872
	60: description="Built-in Audio" prio=2000
*	62: description="Built-in Audio (Loopback PCM)" prio=1984

此 PipeWire 问题报告还提出了一种替代方案:手动添加麦克风。首先确保 ALSA 已检测到麦克风。

$ arecord -l
**** List of CAPTURE Hardware Devices ****
card card_number: card_name, device device_number: device_name
  ...

从列表中选择麦克风,然后运行以下命令进一步测试:

$ arecord --duration=5 --format=dat --device=hw:card_number,device_number test-mic.wav # 从麦克风录音
$ aplay test-mic.wav # 播放录音

如果麦克风可以通过 arecord 正常录音,却未被 PipeWire 检测到,可以尝试创建配置文件,手动添加该设备。

/etc/pipewire/pipewire.conf.d/microphone.conf (or ~/.config/pipewire/pipewire.conf.d/microphone.conf)
context.objects = [
    { factory = adapter
        args = {
            factory.name           = api.alsa.pcm.source
            node.name              = "microphone"
            node.description       = "未检测到的麦克风"
            media.class            = "Audio/Source"
            api.alsa.path          = "hw:card_number,device_number"
        }
    }
]

然后重启 PipeWire 以重新加载配置。

音频质量

节能机制导致爆音

HECI 控制器受到电源管理影响时可能导致爆音。可以通过 powertop 禁用运行时电源管理(Runtime PM)。

音频失真

  • 对于麦克风,在运行 alsamixer 后找到存在问题的声卡,并使用方向键降低“Mic Boost”或“Internal Mic Boost”等麦克风增益选项。
  • 参照#更改默认采样率,将采样率降低至 44100(44.1 kHz)。

更改默认采样率

PipeWire 默认使用固定的 48 kHz 全局采样率。如需更改,可以设置新的默认值(但不推荐):

/etc/pipewire/pipewire.conf.d/sample-rate.conf (or ~/.config/pipewire/pipewire.conf.d/sample-rate.conf)
context.properties = {
    default.clock.rate = sample_rate
}

不过,不建议这样做,因为这会影响延迟,而 quantum 的数值不会自动重新计算。如果希望保持相同的时间比例,则必须自行调整。引用官方文档的说明:

默认时钟采样率决定了最小、最大和默认 quantum 所对应的实时持续时间。更改默认时钟采样率时,你可能需要同时更改 quantum,以保持它们原来的持续时间。

请注意,各音频流自身的采样率不会改变。PipeWire 只会进行重采样,以满足新的输出采样率。因此,原本无需处理的 48 kHz 音频流现在也会被重新采样。

如果设备支持多种采样率,建议保留默认设置,改为按照#更改允许的采样率进行配置。

更改允许的采样率

PipeWire 也可以根据 DAC 所支持的采样率动态改变输出采样率,使其跟随正在播放的音频流。例如:

/etc/pipewire/pipewire.conf.d/sample-rate.conf (or ~/.config/pipewire/pipewire.conf.d/sample-rate.conf)
context.properties = {
    default.clock.allowed-rates = [ 44100 48000 88200 96000 176400 192000 352800 384000 ]
}

假设默认采样率为 48000(即默认设置)。通常,如果音频流以 44100 Hz 输出(例如播放 CD 音质歌曲),PipeWire 会把它重采样到 48 kHz。但是,如果允许列表中包含 44100,PipeWire 则会检查音频流的 44100 是否在允许列表内,以及接收音频的输出设备(例如 DAC)是否支持该采样率。如果都满足,DAC 就能在不进行重采样的情况下播放歌曲。如果采样率不在列表中,或者 DAC 不支持它,PipeWire 就会退回默认采样率并进行重采样。

根据开发者的说法:“PipeWire 最多允许配置 16 种不同采样率,并会在可能时切换。”这意味着上述配置在设备支持时不会进行重采样。自 PipeWire 0.3.61 起,最多可配置 32 种采样率。

获取允许的采样率

查阅硬件手册,确认 DAC 支持的采样率。内核驱动编解码器报告的支持采样率可以通过以下命令查看:

$ grep -E 'Codec|Audio Output|rates' /proc/asound/card*/codec#*

如果 DAC 不报告编解码器信息,可以尝试通过以下命令获取支持的采样率:

$ grep -m1 -Hn "" /proc/asound/card?/stream? | tee /dev/tty | awk -F':' '{print $1}' | xargs grep 'Rates'
注意:虽然 DAC 芯片可能报告高于产品标称规格的采样率,但其中一些仅用于 USB 转 I2S 等特殊模式。

检查当前使用的采样率

运行以下命令,检查某张声卡当前使用的输出采样率:

$ grep rate: /proc/asound/card?/pcm??/sub?/hw_params
/proc/asound/card1/pcm0p/sub0/hw_params:rate: 96000 (96000/1)

在 pcm0p 或 pcm0c 中,c 表示“capture”(采集),p 表示“playback”(播放)。

命令:

$ pw-top

也会显示各声卡和音频流当前使用的采样率。

提示:如果在设置 default.clock.allowed-rates 后,DAC 仍不能切换到更高采样率,可能是系统无法读取 DAC 支持的采样率。这时仍可尝试设置 default.clock.rate。

硬件和声卡

JBL Quantum 350 Wireless 与 Discord 的兼容问题

症状:当 Discord 发起音频输出或初始化音频配置时,没有声音;如果已经有其他声音正在播放,Discord 音频便可正常工作。例如会出现以下错误:

spa.alsa: front:0p: (125 suppressed) snd_pcm_avail after recover: Broken pipe

该错误会出现在 系统日志中。

至少有两种可能的解决方案:提高 api.alsa.headroom(例如设为 512),或设置合适的 api.alsa.start-delay。以下是针对 JBL Quantum 350 无线设备的示例:

~/.config/wireplumber/wireplumber.conf.d/52-jbl-quantum-350-discord-fix.conf
monitor.alsa.rules = [
   {
     matches = [
       {
         node.name = "alsa_output.usb-JBL_JBL_Quantum350_Wireless-00.analog-stereo"
       }
     ]
     actions = {
       update-props = {
         api.alsa.start-delay = 500
       }
     }
   }
 ]

然后在计算机上重启 wireplumber.service 用户单元。

XiiSound / HAVIT Fuxi-H3 (040b:0897)

这款 USB 耳机在 PipeWire 和 WirePlumber 下有几个特殊问题:

  • 仅在音量为 100% 时有声音——硬件音量范围过窄(0.00 dB 至 0.39 dB),使得 PipeWire 的分贝映射将较低音量全部转换为静音。
  • 左声道静音——设备具有一个供左声道使用的次级 ALSA 混音器控制项(PCM,1,numid=10),WirePlumber 未初始化它,导致音量停留在 0%。
  • 麦克风初始化时被静音——PipeWire 可能在启用静音的状态下创建采集源。

修复方法 1——强制使用软件混音器:

创建:

~/.config/wireplumber/wireplumber.conf.d/51-fuxi-h3-fix.conf
monitor.alsa.rules = [
   {
     matches = [
       {
         device.name = "alsa_card.usb-XiiSound_Technology_Corporation_Fuxi-H3-00"
       }
     ]
     actions = {
       update-props = {
         api.alsa.soft-mixer = true
         api.alsa.ignore-dB = true
         api.alsa.split-enable = false
       }
     }
   }
 ]

然后在计算机上重启 wireplumber.service 用户单元。

修复方法 2——恢复左声道:

$ amixer -c 0 cset numid=10 100

修复方法 3——取消麦克风静音:

$ pactl set-source-mute alsa_input.usb-XiiSound_Technology_Corporation_Fuxi-H3-00.mono-fallback 0

使设置在重启后仍然有效:

# alsactl store 0

KDE Plasma 中未显示任何音频设备

PipeWire 客户端(包括桌面环境)可能依赖 XDG_RUNTIME_DIR 环境变量来连接 PipeWire 守护进程。[1] 如果登录后没有出现音频设备,原因可能是该变量被手动设置成了错误的路径。

尽管手动重启 PipeWire 可能暂时解决问题,但仍可能出现其他故障,例如无法在 Chromium 中共享屏幕(提示 pipewire context failed)。XDG_RUNTIME_DIR 会由 pam_systemd(8) 自动设置,因此应删除初始化文件中对它的所有手动赋值。

向 RAOP 设备(Sonos 等)串流时没有声音

使用 Avahi 或 systemd-resolved 配置 mDNS 主机名解析。

从挂起状态恢复后实时优先级丢失/负载下爆音

这一章节正在考虑移除。

原因: 所述缺陷已于 2023 年迁移到 新的 freedesktop.org 仓库后得到修复。 (在 Talk:PipeWire/故障排除 讨论)


由于 rtkit 中一项2011 年报告的缺陷,系统挂起会导致 PipeWire 的实时优先级被撤销,且恢复运行后无法重新获得。若要关闭触发此问题的保护机制,请编辑 rtkit-daemon.service:

/etc/systemd/system/rtkit-daemon.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/lib/rtkit-daemon --no-canary

然后重启 rtkit-daemon.service 系统单元、pipewire.service 用户单元及媒体会话服务。

同一声卡同时向多个音频输出设备输出

复制 /usr/share/alsa-card-profile/mixer/profile-sets/default.conf,以便更新后仍保留自定义更改。这里定义一个将模拟输出与 HDMI 的两个默认映射合并起来的配置文件。

/usr/share/alsa-card-profile/mixer/profile-sets/multiple.conf
[General]
auto-profiles = no

[Mapping analog-stereo]
device-strings = front:%f
channel-map = left,right
paths-output = analog-output analog-output-lineout analog-output-speaker analog-output-headphones analog-output-headphones-2
paths-input = analog-input-front-mic analog-input-rear-mic analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line analog-input-headphone-mic analog-input-headset-mic
priority = 15

[Mapping hdmi-stereo]
description = 数字立体声 (HDMI)
device-strings = hdmi:%f
paths-output = hdmi-output-0
channel-map = left,right
priority = 9
direction = output

[Profile multiple]
description = 模拟立体声双工 + 数字立体声 (HDMI) 输出
output-mappings = analog-stereo hdmi-stereo
input-mappings = analog-stereo

然后配置会话管理器,为匹配的设备使用新的声卡配置文件。可以通过 pw-dump 或 wpctl 获取设备标识信息。

对于 wireplumber包:

/etc/wireplumber/wireplumber.conf.d/alsa-custom.conf (or ~/.config/wireplumber/wireplumber.conf.d/alsa-custom.conf)
monitor.alsa.rules = [
  {
    matches = [
      {
        device.nick = "HDA Intel PCH"
      }
    ]
    actions = {
      update-props = {
        api.alsa.use-acp = true
        api.acp.auto-profile = false
        api.acp.auto-port = false
        device.profile-set = "multiple.conf"
        device.profile = "multiple"
      }
    }
  }
]

对于 pipewire-media-session包:

/etc/pipewire/media-session.d/alsa-monitor.conf (or ~/.config/pipewire/media-session.d/alsa-monitor.conf)
rules = [
    {
        matches = [ { alsa.card_name = "HDA Intel PCH" } ]
        actions = {
            update-props = {
                api.alsa.use-acp = true
                device.profile-set = "multiple.conf"
                device.profile = "multiple"
                api.acp.auto-profile = false
                api.acp.auto-port = false
            }
        }
    }
]

USB DAC 的高延迟问题(例如 Schiit DAC)

更改采样率或音频格式可能有助于降低 Schiit Hel 2 等 DAC 的延迟。[2]

对于 pipewire-media-session包:

将默认配置文件 /usr/share/pipewire/media-session.d/alsa-monitor.conf 复制到 /etc/pipewire/media-session.d/(或 ~/.config/pipewire/media-session.d/)。 然后添加类似下面的规则块:

/etc/pipewire/media-session.d/alsa-monitor.conf (or ~/.config/pipewire/media-session.d/alsa-monitor.conf)
...
rules = {
    ...
    {
        matches = [
            {
                node.name = "alsa_output.name-of-node"
            }
        ]
        actions = {
            update-props = {
                audio.format = "S24_3LE"
                audio.rate = 96000
                # 如果声音仍有中断或其他问题,请逐次将以下数值加倍
                api.alsa.period-size = 128
...

对于 wireplumber包:

/etc/wireplumber/wireplumber.conf.d/update-rate-and-format.conf (or ~/.config/wireplumber/wireplumber.conf.d/update-rate-and-format.conf)
monitor.alsa.rules = [
  {
    matches = [
      {
        node.name = "alsa_output.name-of-node"
      }
    ]
    actions = {
      update-props = {
        audio.format = "S24_3LE"
        audio.rate = 96000
        # 如果声音仍有中断或其他问题,请逐次将以下数值加倍
        api.alsa.period-size = 128
      }
    }
  }
]

可以用 pw-top 获取 alsa_output.name-of-node 节点名称。

你的 DAC 可能支持不同的格式或采样率。可以通过查询 ALSA 来检查 DAC 所支持的参数:

首先获取 DAC 的声卡编号:

$ aplay -l
...
card 3: S2 [Schiit Hel 2], device 0: USB Audio [USB Audio]
  Subdevices: 0/1
  Subdevice #0: subdevice #0
...

因此,本例中的声卡编号为 3。 获取所有受支持的采样率及格式:

$ cat /proc/asound/cardX/streamX
...
Playback:
  ...
  Interface 1
    Altset 1
    Format: S16_LE
    Channels: 2
    Endpoint: 0x05 (5 OUT) (ASYNC)
    Rates: 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000
    Data packet interval: 125 us
    Bits: 16
    ...
  Interface 1
    Altset 2
    Format: S24_3LE
    Channels: 2
    Endpoint: 0x05 (5 OUT) (ASYNC)
    Rates: 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000
    Data packet interval: 125 us
    Bits: 24
    ...
  Interface 1
    Altset 3
    Format: S32_LE
    Channels: 2
    Endpoint: 0x05 (5 OUT) (ASYNC)
    Rates: 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000
    Data packet interval: 125 us
    Bits: 32
    ...
...

本例中,支持的格式为 S16_LE, S24_3LE, S32_LE;所有格式合计支持的采样率为 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000。

USB DAC 音量达到 30% 后才有声音

某些 USB DAC 只有在音量达到一定数值后才能输出声音[3]。通常阈值在 15% 至 30% 左右,这可能导致初始音量过大,并且无法维持低音量。解决方法是将该设备的 api.alsa.soft-mixer 设为 true,忽略硬件混音器的音量控制。

在 wireplumber包 中可以使用以下配置:

/etc/wireplumber/wireplumber.conf.d/alsa-soft-mixer.conf (or ~/.config/wireplumber/wireplumber.conf.d/alsa-soft-mixer.conf)
monitor.alsa.rules = [
  {
    matches = [
      {
        device.name = "alsa_card.name-of-device"
      }
    ]
    actions = {
      update-props = {
        # 不使用硬件混音器控制音量,仅通过软件调节音量。
        # 但仍使用混音器,根据所选端口
        # 将未使用的音频通路静音。
        api.alsa.soft-mixer = true
      }
    }
  }
]

参见 获取用于规则匹配的接口名称,以确定替换 "alsa_card.name-of-device" 所需的正确值。

也可以指定 "~alsa_card.*",将规则应用到所有音频设备。

然后重启 PipeWire,例如运行 systemctl --user restart pipewire。在 alsamixer 中设置主音量,然后以 root 身份执行 alsactl store 保存设置。现在应该可以正常使用音量控制器了。

实时音频无法工作

如果 pipewire.service 用户单元的状态中出现 RTKit error: org.freedesktop.DBus.Error.AccessDenied,说明 PipeWire 守护进程未能获得实时优先级。参见此问题报告。

外接声卡重新连接后未激活

检查 ~/.config/pipewire/media-session.d/default-profile 中是否存在默认配置文件为 "off" 的条目,如有则将其删除。如果仍无法解决,删除 ~/.config/pipewire/media-session.d/ 内的所有文件并重启 pipewire.service 用户单元。

没有声音,或 pactl info 显示 Failure: Connection refused

这意味着应用程序无法连接到 PipeWire-Pulse 服务。请检查 pipewire-pulse.service 用户单元是否正在运行。

如果无法解决问题,请运行 strace -f -o /tmp/pipe.txt pactl info,并将 /tmp/pipe.txt 上传到 pastebin,以便在 IRC(OFTC 上的 #pipewire)或邮件列表上寻求帮助。

连接新设备时声音未自动切换

若要自动切换到新连接的设备,请创建以下文件:

/etc/pipewire/pipewire-pulse.conf.d/switch-on-connect.conf (or ~/.config/pipewire/pipewire-pulse.conf.d/switch-on-connect.conf)
pulse.cmd = [
    { cmd = "load-module" args = "module-switch-on-connect" }
]

然后使用 systemctl --user 重启 pipewire-pulse.service,并检查 module-switch-on-connect 是否已加载。

连接蓝牙设备后没有声音

截至 2020 年 12 月 7 日,如果连接蓝牙设备后没有声音,可能需要切换默认输出设备,或将音频流输入移动到正确的输出设备。使用 pactl list sinks 列出可用输出设备,再使用 pactl set-default-sink 将默认输出切换到蓝牙设备。也可以借助 udev,使用类似这个脚本的方式自动完成。

参见此 Reddit 讨论。根据脚本作者的说法,耳机配置文件(HSP)仍可能存在问题。

蓝牙

蓝牙音频质量低

如果蓝牙播放出现卡顿,请检查 pipewire.service 用户单元的状态,寻找类似以下内容的错误:

Feb 17 18:23:01 HOST pipewire[249297]: (bluez_input.18:54:CF:04:00:56.a2dp-sink-60) client too slow! rate:512/48000 pos:370688 status:triggered

如果出现这些错误,请使用 pactl list sinks 检查当前选择的编解码器,并尝试将 bluez5.codec 设置为 sbc aac ldac aptx aptx_hd 中的一种。还可以尝试 mSBC 支持(可修复 Sony 1000XM3,即 WH-1000XM3 耳机和 WF-1000XM3 真无线耳机的麦克风问题),以及 SBC-XQ 编解码器。

注意:对于 WH-1000XM3 等耳机,如果在配套应用中将“声音质量模式”设置为“优先稳定连接”而不是“优先音质”,耳机就不会公布 SBC/SBC-XQ 以外的其他编解码器。

对于 wireplumber包:

/etc/wireplumber/wireplumber.conf.d/bluez-config.conf (or ~/.config/wireplumber/wireplumber.conf.d/bluez-config.conf)
monitor.bluez.properties = {
  bluez5.enable-sbc-xq = true
  bluez5.enable-msbc = true
  bluez5.codecs = [ sbc sbc_xq ]
}

对于 pipewire-media-session包:

/etc/pipewire/media-session.d/bluez-monitor.conf (or ~/.config/pipewire/media-session.d/bluez-monitor.conf)
...
properties = {
  ...
  bluez5.enable-msbc = true
  bluez5.enable-sbc-xq = true
  bluez5.codecs = [sbc sbc_xq]
...

通过重启 pipewire.service 用户单元来重启 PipeWire,使更改生效。

应用程序

终端提示铃不响

从 PipeWire 的角度来看,必须加载 x11.bell 模块。该模块本应在配置中默认启用(也可以检查前面提到的配置文件)。检查是否安装了 pipewire-x11-bell包 软件包。窗口管理器也可能影响终端提示铃,例如在 xfwm 中需要检查 xfwm-terminal 的设置,确保已启用“Audible bell”(可听提示铃)。然后重启 PipeWire 服务:

$ systemctl --user restart pipewire

可以运行以下命令测试终端提示铃是否正常:

$ echo $'\a'

OBS 等应用无法显示画面,即使已经请求选择窗口或屏幕

如果确信已安装 xdg-desktop-portal包 以及 xdg-desktop-portal-gtk包 或 xdg-desktop-portal-kde包,请检查相关守护进程是否正在运行。

如果 OBS 正常工作,应该在 stdout 中看到以下内容:

...
info: [pipewire] desktop selected, setting up screencast
info: [pipewire] created stream 0x5632d7456850
info: [pipewire] playing stream…

对于多显示器设置,slurp包 软件包可以帮助捕获所有屏幕。

使用 FMOD 的游戏在 PipeWire 下崩溃

一些使用旧版本 FMOD 音频引擎的游戏(例如 永恒之柱)会调用 pulseaudio --check,并在缺少 PulseAudio 可执行文件时崩溃。一种规避方法是创建从 /bin/pulseaudio 指向 /bin/true 的符号链接。[4]

# ln -s /bin/true /bin/pulseaudio

请注意,如果以后要重新安装 PulseAudio,需要先删除该符号链接。

Discord 没有通知声音

这可能是由于 min.quantum 太低;可以尝试将其设置为大于 700 的值。可在 pipewire-pulse.conf 的 pulse.rules 部分添加如下规则,仅覆盖 Discord 的相关设置。

/etc/pipewire/pipewire-pulse.conf (or ~/.config/pipewire/pipewire-pulse.conf)
...
pulse.rules = [
  ...
    {
        # 修复 Discord 通知声音
        matches = [ { application.process.binary = "Discord" } ]
        actions = {
            update-props = {
                pulse.min.quantum      = 1024/48000     # 21ms
            }
        }
    }
...

多个音频流开始播放时声音中断

通常可以通过查看 pipewire-pulse.service 用户单元的日志来诊断此问题,其中可能出现类似以下的记录:

pipewire-pulse[21740]: pulse-server 0x56009b9d5de0: [Nightly] UNDERFLOW channel:0 offset:370676 underrun:940

根据 PipeWire 官方故障排除指南,对于 wireplumber包,可使用以下配置解决:

/etc/wireplumber/wireplumber.conf.d/alsa-config.conf (or ~/.config/wireplumber/wireplumber.conf.d/alsa-config.conf)
monitor.alsa.rules = [
  {
    matches = [
      {
        node.name = "~alsa_output.*"
      }
    ]
    actions = {
      update-props = {
        api.alsa.period-size   = 1024
        api.alsa.headroom      = 8192
      }
    }
  }
]

对于 pipewire-media-session包:

/etc/pipewire/media-session.d/alsa-monitor.conf (or ~/.config/pipewire/media-session.d/alsa-monitor.conf
api.alsa.headroom = 1024

如果音频卡顿是由内核页面锁定或调度不及时造成的,请参见 游戏#调整内核参数以实现响应时间一致性。

其他问题

自动切换功能无法工作

如果自动切换无法正常工作,问题可能出在 WirePlumber 的状态数据上。按照此评论的建议,可以删除 WirePlumber 的本地状态并重启守护进程,查看是否有所改善:

$ rm -r ~/.local/state/wireplumber/

然后重启 wireplumber.service 用户单元。

待机恢复后出现音频问题

如果计算机从睡眠中唤醒后没有声音,或声音异常失真,可能是声卡未能正确恢复。临时解决方法是重启 PipeWire 和 WirePlumber:

# systemctl --user restart pipewire pipewire-pulse wireplumber

增加 RLIMIT_MEMLOCK

Dec 13 11:11:11 HOST pipewire-pulse[99999]: Failed to mlock memory 0x7f4f659d8000 32832: This is not a problem but for best performance, consider increasing RLIMIT_MEMLOCK

安装 realtime-privileges包,并将当前用户加入 realtime 用户组。

另一种方法是将 memlock 限制从 64 kB 提升到 128 kB,这似乎足以修复问题。如果通过 systemd/用户 运行 pipewire-pulse,请添加:

username	soft	memlock	64
username	hard	memlock	128

将这些内容写入 /etc/security/limits.d/username.conf。

开始播放时出现明显延迟或可听见的爆音

这是因为节点在空闲时被挂起。

对于 wireplumber包,创建一个新的配置文件覆盖默认设置:

/etc/wireplumber/wireplumber.conf.d/disable-suspension.conf (or ~/.config/wireplumber/wireplumber.conf.d/disable-suspension.conf)
monitor.alsa.rules = [
  {
    matches = [
      {
        # 匹配所有输入源
        node.name = "~alsa_input.*"
      },
      {
        # 匹配所有输出设备
        node.name = "~alsa_output.*"
      }
    ]
    actions = {
      update-props = {
        session.suspend-timeout-seconds = 0
      }
    }
  }
]
# 蓝牙设备
monitor.bluez.rules = [
  {
    matches = [
      {
        # 匹配所有输入源
        node.name = "~bluez_input.*"
      },
      {
        # 匹配所有输出设备
        node.name = "~bluez_output.*"
      }
    ]
    actions = {
      update-props = {
        session.suspend-timeout-seconds = 0
      }
    }
  }
]

重启 pipewire.service 和 wireplumber.service 使更改生效。

除了完全禁用挂起,也可以更改超时值,指定音频源在多少秒无活动后才挂起。

某些设备自行检测静音并进入休眠。对于这些设备,仅禁用节点挂起仍无效。可以通过添加少量噪声来规避静音检测,使输出始终不会完全静音:

.../disable-suspension.conf
...
    session.suspend-timeout-seconds = 0,  # 0 表示禁用挂起
    dither.method = "wannamaker3", # 添加指定形状的抖动噪声
    dither.noise = 2, # 增加额外的噪声位数
...

可能需要调整 dither.noise 和 dither.method 参数,使噪声既足够安静,又足以防止设备检测到静音。参见 PipeWire 文档。

对于 pipewire-media-session包:

根据延迟发生的位置,编辑 /etc/pipewire/media-session.d/*-monitor.conf,将 session.suspend-timeout-seconds 属性改为 0 以禁用挂起,或者尝试其他数值,观察效果。

也可以在 /etc/pipewire/media-session.d/media-session.conf 中注释掉 suspend-node 这一行。

重启 pipewire.service 与 pipewire-pulse.service 以应用更改,或直接重启计算机。

首次尝试播放后才有声音

如果 PipeWire 通过套接字激活启动,部分原生 PipeWire 应用可能会在 WirePlumber 完成节点配置之前就尝试播放音频,从而出现错误,例如:

$ mpv -v /path/to/file
[ao/pipewire] PipeWire does not have any audio sinks, skipping
[ao] Failed to initialize audio driver 'pipewire'
$ journalctl --user -u mpd.service
output: Failed to play on "PipeWire" (pipewire): no target node available
exception: Failed to open audio output

规避方法是启用 pipewire.service 用户单元。