PipeWire/示例
环绕声系统
分离前/后声道
当使用 PipeWire 作为 PulseAudio/JACK 的替代品时,你可以设置 PipeWire 来复制 Pulseaudio 中分离前/后声道的示例。这样做允许你使用 Pulseaudio 将音频流发送到单独的输出端,用于扬声器或耳机。
将扬声器连接到线路输出端口,耳机连接到后置端口。在 pavucontrol
中,将声卡设置为模拟环绕 4.0 输出。然后使用以下命令,为扬声器和耳机创建新的输出端,将扬声器连接到前置声道,将耳机连接到后置声道
pactl load-module module-null-sink sink_name=speakers object.linger=1 media.class=Audio/Sink channel_map=FL,FR pactl load-module module-null-sink sink_name=headphones object.linger=1 media.class=Audio/Sink channel_map=RL,RR
object.linger=1
使输出端在创建客户端断开连接后仍然保持活动状态。你可以随意命名 sink_name
。
要卸载模块,你可以使用 pw-cli destroy ID
,其中 ID
是 pactl load-module
命令的输出。目前不支持通过 pactl unload-module
卸载单个模块 [1]。但是,你可以使用它来卸载所有 module-null-sink
模块,方法是使用 pactl unload-module module-null-sink
。
使用 jack_connect
,将新输出端的监视器连接到声卡的播放端口。通过运行 pw-link -iol
[2] 找出声道的名称。
pw-link speakers:monitor_1 alsa_output.pci-0000_00_14.2.analog-surround-40:playback_FL pw-link speakers:monitor_2 alsa_output.pci-0000_00_14.2.analog-surround-40:playback_FR pw-link headphones:monitor_1 alsa_output.pci-0000_00_14.2.analog-surround-40:playback_RL pw-link headphones:monitor_2 alsa_output.pci-0000_00_14.2.analog-surround-40:playback_RR
alsa_output.pci-0000_00_14.2.analog-surround-40
替换为你的声卡名称。在脚本执行前添加延迟也可能使事情运行更顺畅。alsa_output.pci-0000_00_14.2.analog-surround-40:playback_FL
有时会更改为 Built-in\ Audio\ Analog\ Surround\ 4.0:playback_FL
。作为快速解决方法,你可以在你的自动启动脚本中添加第二组 pw-jack
命令,使用第二组名称。要单独控制音量,一种选择是使用 alsa 工具(例如 amixer)来控制前置和后置/环绕(alsa 命名)声道。一个根据你当前默认 pulseaudio 输出端自动执行此操作的脚本可以在这里找到。
回声消除
PipeWire 可以实时消除扬声器声音在麦克风中的回声,这使得即使在其他应用程序正在播放音频时,也可以无需使用耳机参加音频聊天。
通常,语音聊天应用程序确实会消除反馈,但它们只知道通过它们的音频。例如,如果另一个语音聊天参与者通过你的扬声器讲话,聊天应用程序“知道”这一点,并能够有选择地从你的麦克风中消除这种噪音,否则这种噪音会作为令人讨厌的回声重复返回到语音聊天中。当其他应用程序正在你的扬声器上播放时,这种方法的问题往往开始出现,因为语音聊天应用程序不知道这些音频,其他参与者可能会听到并抱怨。示例情况:
- 在玩在线视频游戏时使用单独的语音聊天应用程序
- 在使用语音聊天应用程序的同时,使用同步视频播放解决方案,例如 Jellyfin SyncPlay 或 Watch2Gether
这就是系统级回声消除解决的问题;与其让语音聊天应用程序抑制回声——并在上述情况下失败——不如让 PipeWire 来做,它天生“知道”所有在扬声器上播放的音频。
假设 PipeWire 配置为空白,可以通过在 /etc/pipewire/pipewire.conf.d/
中创建一个世界可读的配置文件来启用系统级回声消除,该文件的名称以“.conf”结尾,例如 60-echo-cancel.conf
“aec.args”的默认值可以在这里找到,只需在“aec-webrtc.cpp”中搜索“webrtc.”。
context.modules = [ # Echo cancellation { name = libpipewire-module-echo-cancel args = { # Monitor mode: Instead of creating a virtual sink into which all # applications must play, in PipeWire the echo cancellation module can read # the audio that should be cancelled directly from the current fallback # audio output monitor.mode = true # The audio source / microphone wherein the echo should be cancelled is not # specified explicitly; the module follows the fallback audio source setting source.props = { # Name and description of the virtual source where you get the audio # without echoed speaker output node.name = "source_ec" node.description = "Echo-cancelled source" } aec.args = { # Settings for the WebRTC echo cancellation engine webrtc.gain_control = true webrtc.extended_filter = false # Other WebRTC echo cancellation settings which may or may not exist # Documentation for the WebRTC echo cancellation library is difficult # to find #webrtc.analog_gain_control = false #webrtc.digital_gain_control = true #webrtc.experimental_agc = true #webrtc.noise_suppression = true } } } ]
诸如此类的配置更改需要 PipeWire 重启(即 pipewire.service
和 pipewire-pulse.service
用户单元)才能生效。
将额外的音频混合到麦克风音频中
上面的回声消除示例可以扩展为提供一个虚拟输出端,将音频复制到你的麦克风中。
它是 PulseAudio/Examples#Mixing additional audio into the microphone's audio 的重新创建,并解决了相同的用例。
为了实现这一点,你还需要加载两个“Combine stream”模块的实例,如下所示。
目前,在每次重启或 PipeWire 重启后,设置需要用户手动操作,例如在 Helvum 中才能完成;请参阅配置示例中的“TODO”注释。
context.modules = [ # (Configuration for system-wide echo cancellation, see above) # Audio effects sink (stereo) { name = libpipewire-module-combine-stream args = { combine.mode = sink node.name = sink_fx node.description = "Effects sink (play shared audio here)" combine.props = { audio.position = [ FL FR ] } stream.props = { # If you have an upmix configuration in client.conf.d, set the same # parameters here, or else your sound effects application will not # be upmixed in your local audio output #channelmix.upmix = true # (...) # Possible alternative: Poor man's stereo upmix, i.e. mirroring front # to rear speakers #combine.audio.position = [ FL FR FL FR ] #audio.position = [ FL FR RL RR ] } } } # Main source # Virtual source that supplies these sources mixed together: # - source_ec (Echo-cancelled source) # - sink_fx.monitor (Monitor of the audio effects sink) { name = libpipewire-module-combine-stream args = { combine.mode = source node.name = source_main node.description = "Main source (record from here)" #combine.latency-compensate = false combine.props = { audio.position = [ FL FR ] } stream.rules = [ { matches = [ { node.name = "source_ec" media.class = "Audio/Source" } ] actions = { create-stream { } } } # TODO Block with matches= and actions= that matches the monitor of # sink_fx and hooks it up to source_main # No PipeWire configuration known yet that automates this # See this PipeWire issue for news: # https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/3710 # For the time being, add the required connections manually in Helvum, # i.e. connect these points: # - sink_fx.monitor_FL -> source_main.output.input_FL # - sink_fx.monitor_FR -> source_main.output.input_FR ] } } ]