Pipewire

From miki
Jump to navigation Jump to search

Pipewire is the new sound system on Linux, meant to replace Pulseaudio.

Links

WirePlumber
Nice examples on how to use the lua configuration files.
Link to an nice blog on wireplumber (explanation).

References

Configuration files:

  • /usr/share/pipewire
  • /usr/share/wireplumber

Commands

# View status
systemctl --user status pipewire

# Use PipeWire instead of JACK
pw-jack SOMEAPP

# PipeWire process viewer (quantum usage...)
pw-top

# Setup sinks, sources, audio devices
pw-link
qjackctl         # Graphical tool, leveraging on JACK
qpwgraph         # Alternative, pipewire native

# Get settings
pw-metadata -n settings

# Set settings
pw-metadata -n settings 0 clock.rate 48000
pw-metadata -n settings 0 clock.allowed-rates '[ 48000, 96000, 44100 ]'

# Command line
pw-cli
> info all

# wireplumber
wpctl status

# wireplumber - troubleshooting
wpctl status        # verify the default endpoints
pw-record test.wav  # ... can also set target...
pw-play test.wav
# ... more at https://pipewire.pages.freedesktop.org/wireplumber/testing.html#wireplumber-examples

Configuration

  • Package configuration files are located in /usr/share/pipewire and /usr/share/wireplumber.
  • To change them, copy and edit them in /etc/pipewire (system-wide) or ~/.config/pipewire (local changes).
pipewire-pulse.conf
  • A single section can also be updated through a file in /etc/pipewire/pipewire-pulse.conf.d/ or ~/.config/pipewire/pipewire-pulse.conf.d/
cat /usr/share/pipewire/pipewire-pulse.conf
# # PulseAudio config file for PipeWire version "0.3.50" #
# #
# # Copy and edit this file in /etc/pipewire for system-wide changes
# # or in ~/.config/pipewire for local changes.
# #
# # It is also possible to place a file with an updated section in
# #  for system-wide changes or in
# # ~/.config/pipewire/pipewire-pulse.conf.d/ for local changes.
  • One can see current module configuration with pactl:
pactl list modules      # See active modules and their config

Troubleshooting

Setting and keeping bluetooth profile for headset

We want to use the profile sbc sbc_xq for our BT headset Sony WH-1000XM3.

EASIEST METHOD — Select the profile Gnome Settings / pactl
  • See also [1]
  • Selected profile is persistent on reboot / reconnect.
  • Select the profile in Gnome Settings - Sound, or:
# See available profile and device id with 'pactl list'
pactl set-card-profile bluez_card.38_18_4C_4B_6A_3A a2dp-sink-sbc_xq
Select wanted profile in pipewire / wireplumber
  • (pipewire-media-session) When using pipewire-media-session, the default profile could be selected in bluez-monitor.conf, but this file no longer exists with WirePlumber.
  • (wireplumber) Edit /etc/wireplumber/bluetooth.lua.d/51-bluez-config.lua (or ~/.config/wireplumber/bluetooth.lua.d/51-bluez-config.lua) Archlinux - Pipewire:
bluez_monitor.properties = {
  ["bluez5.enable-sbc-xq"] = true,
  ["bluez5.enable-msbc"] = true,
  ["bluez5.codecs"] = "[sbc sbc_xq]",
}
Profile auto-switch
# This simulates capture throug PulseAudio for telephony, and trigger profile switch.
# Opening Gnome Settings, we should see profile switching from mSBC / A2DP.
parec --property=media.role=Communication | pacat

Crackling / Stuttering audio

This applies in a VM. Not sure these apply when PipeWire is run on the host.

Note that recent PipeWire already supports different auto-config if running in a vm [2].

Enable multi-user / network audio

References
An advanced config that allows to share the unix socket, for even lower latency. Use case was specifically for streaming audio coming from a VM!

Currently PipeWire support sharing through network using Pulse, but auth-anonymous is always turned on (auth-ip-acl not implemented).

  • (pipewire 0.3.50+) On the main user, create file ~/.config/pipewire/pipewire-pulse.conf.d/multi-user-zeroconf.conf
# This config file is a refinement of config file /usr/share/pipewire/pipewire-pulse.conf.

# We listen to network socket to enable multi-user / network playback.
# LIMITATION: The laptop speaker is advertised by zeroconf, but playback fails. Playback through BT headset is ok though.
# LIMITATION: auth-ip-acl might not work
# LIMITATION: We listen to ipv4 0.0.0.0 only, and use firewall to further restrict access to private network only.
context.exec = [
    { path = "pactl"        args = "load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 listen=0.0.0.0" }
    { path = "pactl"        args = "load-module module-zeroconf-publish" }
]

# # Below, an alternative way for multi-user / network (however we still need zeroconf above)
# # Note that this method doesn't load the native-protocol-tcp module
# pulse.properties = {
#     # the addresses this server listens on
#     server.address = [
#         "unix:native"
#         "tcp:4713"                         # IPv4 and IPv6 on all addresses
#         # "tcp:127.0.0.1:4713"               # IPv4 on a single address
#         #
#         #{ address = "tcp:4713"             # address
#         #  max-clients = 64                 # maximum number of clients
#         #  listen-backlog = 32              # backlog in the server listen queue
#         #  client.access = "restricted"     # permissions for clients
#         #}
#     ]
#     # vm.overrides = {
#     #     pulse.min.quantum = 1024/48000      # 22ms
#     # }
# }
Note: we CANNOT edit pipewire-pulse.conf or any system-level file (like in /etc/pipewire/pipewire-pulse.d) because the TCP socket would already be used, and service would fail to load.
Now, restart pipewire-pulse, and check it works:
# We must restart the SOCKET (this also restart the SERVICE)
systemctl --user restart pipewire-pulse.socket
PULSE_SERVER=tcp:127.0.0.1:4713 pactl info
PULSE_SERVER=unix:/run/user/1000/pulse/native pactl info
  • On the secondary user:
# We can either export this variable
export PULSE_SERVER=127.0.0.1            # OR ...
export PULSE_SERVER=tcp:127.0.0.1:4713
PULSE_SERVER=127.0.0.1 pactl info
Or we can edit ~/.pulse/client.conf like we did with PulseAudio:
default-server = 127.0.0.1
Note: make sure the port is allowed in the firewall as well.
# ################# NOT TESTED #############################
context.modules = [
{   name = libpipewire-module-pulse-tunnel
    args = {
        tunnel.mode = playback
        # Set the remote address to tunnel to
        pulse.server.address = "tcp:192.168.1.126"
        #audio.rate=<sample rate>
        #audio.channels=<number of channels>
        #audio.position=<channel map>
        #node.target=<remote target node>
        stream.props = {
            # extra sink properties
        }
    }
}
]
We can also use the PipeWire Module: Zeroconf Discover, that will automatically create sinks/sources to/from remote PulseAudio servers.
context.modules = [
{   name = libpipewire-module-zeroconf-discover
    args = { }
}
]
VMWare VM
  • We cannot get audio to work on VMWare VM, under user vbox, although same user can play audio file with eg mplayer.
  • Instead we share the pipewire unix socket, as explained here.
  • Pipewire unix socket for main user is located at /run/user/1000/pipewire-0:
ss -lpn | grep pipewire-0
# u_str LISTEN 0  4096  /run/user/1000/pipewire-0 26175  * 0  users:(("pipewire",pid=2207,fd=3),("systemd",pid=2190,fd=32))
  • We must share this socket with user vbox, but keeping some access control.
  • We create a folder /mnt/pipewire, with access for group audio, and we add user vbox to that group.
sudo mkdir /mnt/pipewire
sudo chgrp audio /mnt/pipewire
sudo chmod 750 /mnt/pipewire
sudo gpasswd -a vbox audio       # This also likely help to get access to ALSA
  • We add a binding mount point in fstab, that can be mounted by user (option user):
# Pipewire audio sharing (for user vbox). This requires:
#   sudo mkdir /mnt/pipewire
#   sudo chgrp audio /mnt/pipewire
#   sudo chmod 750 /mnt/pipewire
#   sudo gpasswd -a vbox audio
/run/user/1000/pipewire-0 /mnt/pipewire/pipewire-0 none bind,rw,user,noauto 0 0
  • We add systemd override to pipewire.socket, to mount/umount that point automatically.
systemctl edit --user pipewire.socket # or edit file '~/.config/systemd/user/pipewire.socket.d/override.conf'
# [Socket]
# ExecStartPost=/bin/mount /mnt/pipewire/pipewire-0
# ExecStopPre=/bin/umount /mnt/pipewire/pipewire-0
  • As user vbox, simply add to ~vbox/.profile:
export PIPEWIRE_RUNTIME_DIR=/mnt/pipewire
Check ALSA works:
aplay -L
  • Alternatively, we can tell sudo to keep variable PIPEWIRE_RUNTIME_DIR. Edit /etc/sudoers.d/envkeep:
visudo /etc/sudoers.d/envkeep
# Defaults env_keep += "http_proxy https_proxy GREP_OPTIONS DISPLAY XAUTHORITY HOME PIPEWIRE_RUNTIME_DIR"
  • Recent version of pipewire also requires this extra package:
sudo apt install pipewire-alsa

troubleshooting Sony WH-1000XM3

Currently

  • SBC_XQ profile works correctly (good audio)
  • headset-head-unit-msbc profile works when using the microphone, but there is a audio loopback in the headset (we hear what the mic captures).

Some background info:

  • [3] Check this page for background info on Bluetooth profiles, HSP vs HFP.
  • Basically HSP is older than HFP, the latter being more convenient.
  • Audio Gateway are basically the mobile phone itself.
  • Here they suggest to set
bluez5.headset-roles = [hsp_hs hsp_ag hfp_hf]

troubleshooting: no more audio on multi-user

After upgrade to pipewire 0.3.64-2 (over 0.3.51-1), we don't have audio anymore on other users (pipewire shared through {{{1}}} socket).

mplayer tells us:

AO: [pulse] Init failed: Connection refused
Failed to initialize audio driver 'pulse'
[AO_ALSA] alsa-lib: dlmisc.c:337:(snd_dlobj_cache_get0) Cannot open shared library libasound_module_pcm_pipewire.so (/lib/x86_64-linux-gnu/alsa-lib/libasound_module_pcm_pipewire.so: cannot open shared object file: No such file or  directory)
[AO_ALSA] Playback open error: No such device or address
Failed to initialize audio driver 'alsa'

The fix is to install the package pipewire-alsa:

apt-file search libasound_module_pcm_pipewire.so
# pipewire-alsa: /usr/lib/x86_64-linux-gnu/alsa-lib/libasound_module_pcm_pipewire.so
sudo apt install pipewire-alsa

troubleshooting: no more audio when changing network

If using firewall to restrict zeroconf access, make sure to edit firewall rule.