WirePlumber

Related articles
PipeWire
WirePlumber
is a powerful session and policy manager for
PipeWire
. Based on a modular design, with Lua plugins that implement the actual management functionality, it is highly configurable and extendable.
Installation
Install
the
wireplumber
package. Any conflicting PipeWire Session Managers will be uninstalled.
WirePlumber uses systemd
user units
to manage the server.
Configuration
Configuration file layout
WirePlumber's configuration
comprises global PipeWire-flavored JSON objects such as
context
and
alsa_monitor
that are modified to change its behavior. The configuration files are read from
~/.config/wireplumber/
(user configuration),
/etc/wireplumber/
(global configuration), and then
/usr/share/wireplumber/
(stock configuration).
WirePlumber starts by reading the
main configuration file
. This is a JSON-like file that sets up the PipeWire context,
SPA plugins
, modules, and components.
The single-instance configuration file at
/usr/share/wireplumber/wireplumber.conf
is the default configuration, which includes the functionality of all the other configurations within one process. See the documentation for the
ALSA objects
,
"access" objects
and
Bluetooth objects
.
Modifying the configuration
The recommended way to configure WirePlumber is to add an
SPA-JSON
file to the appropriate
wireplumber.conf.d/
directory within
/etc/wireplumber/
or
~/.config/wireplumber/
.
User configuration files have a higher priority than system files. Configuration files with the same name but in a lower priority location will be ignored. Within each configuration directory, the individual files are opened in alphanumerical order. See the
documentation
for details.
Obtain interface name for rules matching
In the configuration, you need to specify
matches
rules with a property from an
object
of the interface you want to configure.
Use the command
wpctl status
to show all objects managed by WirePlumber. Find the
ID
assigned to the target interface. Then use command
wpctl inspect
ID
to get a needed property.
For example, if your target interface is
HD Audio Controller Analog Stereo
, consider the following output:
$ wpctl status
PipeWire 'pipewire-0' [0.3.56, user@hostname, cookie:1163266174]

Audio
 ├─ Devices:
 │      42. HD Audio Controller                 [alsa]
 │     105. USB PnP Audio Device                [alsa]
 │
 ├─ Sinks:
 │  *
48. HD Audio Controller Analog Stereo
[vol: 0.50]
 │
 ├─ ...
 │
 ├─ Sources:
 │  *  101. USB PnP Audio Device Mono           [vol: 0.74]
 │
 └─ ...
the interface
ID
is
48
.
Then use the inspect command to view the object's detail and list all properties in that object:
$ wpctl inspect 48
id 48, type PipeWire:Interface:Node
    ...
    device.api = "alsa"
    device.class = "sound"
  * device.id = "42"
    device.profile.description = "Analog Stereo"
    device.profile.name = "analog-stereo"
    ...
  * factory.id = "18"
    factory.mode = "merge"
    factory.name = "api.alsa.pcm.sink"
    ...
  * media.class = "Audio/Sink"
  * node.description = "HD Audio Controller Analog Stereo"
  * node.name = "alsa_output.pci-0000_08_00.4.analog-stereo"
  * node.nick = "ALC1220 Analog"
    ...
  * object.path = "alsa:pcm:1:front:1:playback"
  * object.serial = "49"
    ...
Choose the
device.name
or
node.name
property to use with the
matches
rules in the configuration.
Avoid using
device.id
; it is dynamic and changes often.
Multiple properties in
matches
rules are possible; see the
alsa_monitor.rules
section in the
documentation for the WirePlumber ALSA configuration
.
Note
You can determine the
Endpoint
class of this object from the
media.class
property.
For ALSA,
node
objects are Sinks or Sources /
device
objects correspond to the card.
Since v0.4.9, ALSA nodes use the PCM name to populate
node.nick
, which is useful at least on HDA cards using UCM, where all outputs (analog, HDMI, etc.) are exposed as
Node
on a single profile.
Tip
The command
pw-top
shows the PipeWire
Device
and
Node
currently in use.
Similar inspection command from PipeWire is
pw-cli info
ID
.
Changing a device/node property
To change a device or node property, such as its description or nick, you must create an
SPA-JSON
file and add it into
/etc/wireplumber/
or
~/.config/wireplumber/
under the proper path and name.
For instance, to change the description of an ALSA node, you would create a file such as:
/etc/wireplumber/wireplumber.conf.d/device-rename.conf (or ~/.config/wireplumber/wireplumber.conf.d/device-rename.conf)
monitor.alsa.rules = [
  {
    matches = [
      {
        node.name = "alsa_output.pci-0000_00_1f.3.output_analog-stereo"
      }
    ]
    actions = {
      update-props = {
        node.description = "Laptop"
      }
    }
  }
]
If instead you wish to change something on a Bluetooth node or device, you could create a file such as:
/etc/wireplumber/wireplumber.conf.d/bluez-rename.conf (or ~/.config/wireplumber/wireplumber.conf.d/bluez-rename.conf)
monitor.bluez.rules = [
  {
    matches = [
      {
        node.name = "bluez_output.02_11_45_A0_B3_27.a2dp-sink"
      }
    ]
    actions = {
      update-props = {
        node.nick = "Headphones"
      }
    }
  }
]
The properties that you can change as well as the matching rules to select devices or nodes are documented at
ALSA configuration
and
Bluetooth configuration
.
Disable a device/node
Any devices or nodes can be disabled by setting the property
device.disabled
for devices or
node.disabled
for nodes:
/etc/wireplumber/wireplumber.conf.d/alsa-disable.conf (or ~/.config/wireplumber/wireplumber.conf.d/alsa-disable.conf)
monitor.alsa.rules = [
  {
    matches = [
      {
        device.name = "alsa_card.pci-0000_08_00.4"
      }
    ]
    actions = {
      update-props = {
         device.disabled = true
      }
    }
  }
]
Find a unique identifier for your device or node as seen in
#Obtain interface name for rules matching
.
In this example, matching is done based on the
device.name
, but it can also be done for any other identifying property, such as
node.nick
.
Note
Keep in mind that if you match for a node property instead of a device property, you will have to use
node.disabled
instead of
device.disabled
.
A common use case, for example, is disabling a graphics card's HDMI audio output.
This approach can also be used to disable audio over HDMI for specific displays only, by matching for specific nodes using something like
node.nick
, as this can change depending on the plugged-in device.
Setting node priority
To change which sink or source is automatically selected, you need to set its
priority.driver
and
priority.session
values:
/etc/wireplumber/wireplumber.conf.d/set-priorities.conf
monitor.alsa.rules = [
  {
    matches = [
      {
        node.name = "alsa_output.usb-Generic_USB_Audio-00.HiFi__Speaker__sink"
      }
    ]
    actions = {
      update-props = {
        priority.driver = 100
        priority.session = 100
      }
    }
  }
]
This example sets the priority of the speaker output sink of the on-board audio on the Asus B650E-F motherboard to 100, lowered from the original value of 1000. Consequently, the other output sinks, such as the S/PDIF output of the onboard audio device or the plugged in headphones, will be selected by default due to their higher priorities, instead of the analog speaker output.
Simultaneous output to multiple sinks on the same sound card
See
PipeWire#Simultaneous output to multiple sinks on the same sound card
.
Simultaneous output to transient devices
You may wish to output sound to onboard and external devices simultaneously - even when the external devices are not always plugged in.
To accomplish this we create a virtual node that will always be present, regardless of what hardware is plugged in. We then link the transient hardware (in this example USB headphones) to the virtual node whenever they are plugged in.
First, create a script to run during login; this is usually easiest to do via your window manager's Startup function.
/usr/local/sbin/create-virtual-sink.sh
#!/bin/bash

# Create a new sink called Simultaneous Output
pw-cli create-node adapter '{ factory.name=support.null-audio-sink node.name="Simultaneous Output" node.description="Simultaneous Output" media.class=Audio/Sink object.linger=true audio.position=[FL FR] }'

# Connect the normal permanent sound card output to the new sink
pw-link "Simultaneous Output:monitor_FL" alsa_output.pci-0000_05_04.0.analog-stereo:playback_FL
pw-link "Simultaneous Output:monitor_FR" alsa_output.pci-0000_05_04.0.analog-stereo:playback_FR

# Switch the default output to the new virtual sink
wpctl set-default `wpctl status | grep "\. Simultaneous Output" | egrep '^ │( )*[0-9]*' -o | cut -c6-55 | egrep -o '[0-9]*'`
In the above example, initially the only output device is our 'normal' on-board soundcard (alsa_output.pci-0000_05_04.0.analog-stereo). You can find the designator for your card by running
wpctl status
and
wpctl inspect
.
Run the following script when your USB headphones are inserted in order to link them to the virtual sink:
link-virtual-sink-headphones.sh
#!/bin/bash
# link the virtual sync to your headphones should run when detected by UDEV

# wait a second for the drivers to load
sleep 1s

# link the headphones to your virtual sink
sudo -u user1 env XDG_RUNTIME_DIR=/run/user/1000 pw-link "Simultaneous Output:monitor_FL" alsa_output.usb-Kingston_HyperX_Cloud_Flight_S_000000000001-00.analog-stereo:playback_FL
sudo -u user1 env XDG_RUNTIME_DIR=/run/user/1000 pw-link "Simultaneous Output:monitor_FR" alsa_output.usb-Kingston_HyperX_Cloud_Flight_S_000000000001-00.analog-stereo:playback_FR

# finish and return the code for success
exit 0
Ideally you would run this script automatically when your headphones are inserted. The instructions on the
udev
page describe how you would create a custom rule for that. (Although note that you cannot run this script directly - because udev will not load drivers until
after
any specified script has run. So you will have to have an intermediate script with some nohup trickery or something like that).
You will also need to modify the above script so that the XDG_RUNTIME_DIR matches your user id number and
user1
will need to be replaced with your username.
You can add any arbitrary number of devices to this virtual sink in the same manner.
If you are having trouble keeping track what devices are connected where, the
qpwgraph
tool is excellent for getting a visual representation of which devices are connected to each other.
Tips and tricks
Delete corrupt settings
If the settings of WirePlumber are corrupted it is possible to delete all user settings.
Stop
the
wireplumber.service
user unit
, delete the settings with:
$ rm -r ~/.local/state/wireplumber
Then, you can
start
the
wireplumber.service
user unit
back.
Keyboard volume control
See
Keyboard shortcuts#Xorg
to bind the following commands to your volume keys:
XF86AudioRaiseVolume
,
XF86AudioLowerVolume
,
XF86AudioMute
and
XF86AudioMicMute
.
To raise the volume, with a limit of 150%:
$ wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%+
To lower the volume:
$ wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
To mute/unmute the volume:
$ wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
To mute/unmute the microphone:
$ wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
Tip
To use sinks or sources other than the default ones, run
wpctl status
to list all available sinks, and use sink or source numbers in place of
@DEFAULT_AUDIO_SINK@
or
_SOURCE@
.
Show volume level
To get the volume level and mute status of the default sink:
$ wpctl get-volume @DEFAULT_AUDIO_SINK@
Volume: 0.45
Note
The mute status is only visible when the sink is muted.
Disable Bluetooth profile auto-switching
See
PipeWire#Automatic profile selection
.
Keep Bluetooth running after logout / Headless Bluetooth
Note
You also need to enable
lingering
for the user running
PipeWire
/Wireplumber.
Since 0.4.8 the requirement to
support.logind
has to be disabled for the bluez seat-monitoring.
~/.config/wireplumber/wireplumber.conf.d/disable-logind.conf
wireplumber.profiles = {
  main = {
    monitor.bluez.seat-monitoring = disabled
  }
}
Disable audio stack integration
If you do not want
PipeWire
/Wireplumber to take over control of your audio devices because you are opting for a different audio solution (e.g.
PulseAudio
/
JACK
/
ALSA
) but still want it to be available for screen sharing/video purposes you can make use of the
wireplumber@.service
template unit
to enable a different set of default profiles. Wireplumber ships with a profile configuration that enables only the video parts and disables audio integration (including Bluetooth audio) by enabling the
video-only
template
user unit
.
Disable
wireplumber.service
user unit
and
enable
wireplumber@video-only.service
user unit.
Adjust volume for applications not currently playing audio
Some applications (e.g. launchers) play sound too briefly to adjust their volume using GUI mixers. WirePlumber stores per-application and per-node volume and mute states in a text file at
$HOME/.local/state/wireplumber/stream-properties
. This file can be edited manually to change these settings. Ensure WirePlumber is
not
running while editing, or it may overwrite the changes.
Troubleshooting
Since WirePlumber only exists to manage PipeWire sessions, WirePlumber-related fixes may be found in
PipeWire#Troubleshooting
.
See also
Documentation
— Official documentation
WirePlumber, the PipeWire session manager
— Blog post by George Kiagiadakis (Collabora) from May 2020, detailing how WirePlumber works