PipeWire

Related articles
/Examples
Sound system
WirePlumber
PipeWire
is a new low-level multimedia framework. It aims to offer capture and playback for both audio and video with minimal latency and support for
PulseAudio
,
JACK
,
ALSA
and
GStreamer
-based applications.
The daemon based on the framework can be configured to be both an audio server (with PulseAudio and JACK features) and a video capture server.
PipeWire also supports containers like
Flatpak
and does not rely on the
audio
and
video
user groups
. Instead, it uses a
Polkit
-like security model, asking Flatpak or Wayland for permission to record screen or audio.
Installation
Install
the
pipewire
package from the official repositories. There is also
lib32-pipewire
for
multilib
support.
Optionally, install
pipewire-docs
to review the documentation.
Pipewire can work as drop-in replacement for other audio servers. See
#Audio
for details.
Session manager
Like
JACK
, PipeWire implements no connection logic internally. The burden of watching for new streams and connecting them to the appropriate output device or application is left to an external component known as a session manager.
WirePlumber
WirePlumber
is the recommended session manager. It is based on a modular design, with Lua plugins that implement the actual management functionality.
The stock configuration files are stored in
/usr/share/wireplumber
. The recommended way to customize Wireplumber is adding snippets overriding specific settings in
/etc/wireplumber
or
~/.config/wireplumber
.
[1]
.
WirePlumber changed its configuration format in version 0.5 from
.lua
to
.conf
. See
https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/migration.html#config-migration
for migration instructions.
PipeWire Media Session
pipewire-media-session
is deprecated and no longer recommended. It was mostly implemented for testing and as an example for building new session managers.
Startup
Pipewire uses
systemd/User
for management of the server and automatic
socket activation
: it will start automatically when needed.
To preemptively start PipeWire at login,
enable/start
the
pipewire.service
,
pipewire-pulse.service
and
wireplumber.service
user units
.
GUI
Cable
— A PyQt application to dynamically modify PipeWire and WirePlumber settings at runtime.
https://github.com/magillos/Cable
||
cable
AUR
coppwr
— Low level control and diagnostic GUI for PipeWire.
https://github.com/dimtpap/coppwr
||
coppwr
AUR
Helvum
— GTK-based patchbay for PipeWire, inspired by the JACK tool
catia
. Does not save wire sets.
https://gitlab.freedesktop.org/pipewire/helvum
||
helvum
pwvucontrol
— Pipewire Volume Control. Alternative to pavucontrol.
https://github.com/saivert/pwvucontrol
||
pwvucontrol
AUR
qpwgraph
— Qt-based Graph/Patchbay for PipeWire, inspired by the JACK tool QjackCtl. Saves wire sets.
https://gitlab.freedesktop.org/rncbc/qpwgraph
||
qpwgraph
sonusmix
— Pipewire audio routing tool
https://codeberg.org/sonusmix/sonusmix
||
sonusmix
AUR
TUI
pipemixer
— A TUI volume control application for pipewire built with ncurses.
https://github.com/heather7283/pipemixer
||
pipemixer
AUR
wiremix
— A simple TUI audio mixer for PipeWire.
https://github.com/tsowell/wiremix
||
wiremix
Configuration
The PipeWire package provides an initial set of
configuration files
in
/usr/share/pipewire
. You should not edit these files directly, as package updates will overwrite your changes. To configure PipeWire, you can copy files from
/usr/share/pipewire
to the alternate system-wide location
/etc/pipewire
, or to the user location
~/.config/pipewire
. An equally named file in a directory with a higher precedence makes the analogous files ignored.
PipeWire brings a custom
Pro Audio
(do not confuse with
pro audio
) profile in addition to the PulseAudio profiles, selectable through
pavucontrol
.
Usage
Audio
PipeWire can be used as an audio server, similar to PulseAudio and JACK. It aims to replace both PulseAudio and JACK, by providing a PulseAudio-compatible server implementation and ABI-compatible libraries for JACK clients. See the blog post
PipeWire Late Summer Update 2020
for more information.
First, install
pipewire-audio
. Depending on the type of audio clients, you may also need to take some extra steps. You may need to install additional firmware for your audio device, see
Advanced Linux Sound Architecture#Firmware
.
ALSA clients
Install
pipewire-alsa
(and remove
pulseaudio-alsa
if it was installed) to route all applications using the ALSA API through PipeWire.
PulseAudio clients
Install
pipewire-pulse
. It will replace
pulseaudio
and
pulseaudio-bluetooth
. Reboot, re-login or
stop
pulseaudio.service
and
start
the
pipewire-pulse.service
user unit
to see the effect.
Normally, no further action is needed as the user service
pipewire-pulse.socket
should be enabled automatically by the package. To check if the replacement is working, run the following command for the
Server Name
and default input/output:
$ pactl info
...
Server Name: PulseAudio (on PipeWire
x.y.z
)
...
Default Sink: alsa_output.{bus}-{device}.{profile}
Default Source: alsa_input.{bus}-{device}.{profile}
...
pactl(1)
is provided by PulseAudio client library package (
libpulse
), which is installed with
pipewire-pulse
as a dependency.
Setting overall or individual channel volume
To adjust output channel volume, the
sink
needs to be specified using
pactl get-sink-volume {sink
} using the value of
Default Sink:
(above) or
Name:
(below), default sink device (
@DEFAULT_SINK@
), or
Sink #
(e.g.
1
below):
$ pactl list sinks | grep -B1 -A9 State:
Sink #1
        State: RUNNING
        Name: alsa_output.pci-0000_2d_00.4.analog-surround-51
...
        Driver: PipeWire
...
        Mute: no
        Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB,   rear-left: 65536 / 100% / 0.00 dB,   rear-right: 65536 / 100% / 0.00 dB,   front-center: 65536 / 100% / 0.00 dB,   lfe: 65536 / 100% / 0.00 dB
                balance 0.00
Hint: if audio is playing,
grep(1)
for
RUNNING
as other devices will be
SUSPENDED
.
The
balance
ratio is calculated automatically. To set the overall volume of the default device use:
pactl set-sink-volume @DEFAULT_SINK@ 75%
To set individual channels, provide each channel volume separately:
pactl set-sink-volume @DEFAULT_SINK@ 100% 75% 100% 75% 100% 100%
Source
inputs are handled similarly.  For further configuration (e.g. regarding modules) see the official upstream Wiki about
Migration from PulseAudio
and
Pipewire-Pulse Configuration
.
JACK clients
Install
pipewire-jack
for
JACK
support. There is also
lib32-pipewire-jack
for
multilib
support.
pw-jack(1)
may be used to start JACK clients, but it is technically not required, as it only serves as a wrapper around the
PIPEWIRE_REMOTE
,
PIPEWIRE_DEBUG
and
PIPEWIRE_LATENCY
environment variables.
It is possible to request a custom buffer size by setting a quotient of buffersize/samplerate (which equals the block latency in seconds):
PIPEWIRE_LATENCY="128/48000"
application
Bluetooth devices
PipeWire handles
Bluetooth audio devices
if the
pipewire-audio
package is installed.
Automatic profile selection
WirePlumber
has profile auto-switching enabled by default. It can automatically switch between HSP/HFP and A2DP profiles whenever an input stream is detected. You can disable it with the following command:
$ wpctl settings --save bluetooth.autoswitch-to-headset-profile false
pipewire-media-session
has it disabled by default. You can set
bluez5.autoswitch-profile
property to
true
to enable it:
/etc/pipewire/media-session.d/bluez-monitor.conf (or ~/.config/pipewire/media-session.d/bluez-monitor.conf)
...
rules = [
    {
        ...
        actions = {
            update-props = {
                ...
bluez5.autoswitch-profile = true
...
PipeWire patch sets for command line
qpwgraph
can be used to visualize and create connections, and also save and load patch sets.
For non-GUI needs, the following are bash scripts to save wiresets, load wiresets, and dewire all connections. For saving and loading, use a command-line parameter for the filename.
pw-savewires
#!/bin/bash

if [[ "$#" -ne 1 ]]; then
    echo
    echo 'usage: pw-savewires filename'
    echo
    exit 1
fi

rm -- "$1" &> /dev/null

link_nodeOutput=''

while IFS= read -r line; do
    if [[ "$line" =~ [|] ]];
    then
        link_nodeInput=`echo $line | cut -d ">" -f 2`
        echo "Saving $link_nodeOutput, ${link_nodeInput//' '}"
        echo "$link_nodeOutput ${link_nodeInput//' '}" >> "$1"
    else
        link_nodeOutput="$line"
    fi
done < <(pw-link -lo)
pw-loadwires
#!/bin/bash

if [[ "$#" -ne 1 ]]; then
    echo
    echo 'usage: pw-loadwires filename'
    echo
    exit 1
fi

while IFS= read -r line; do
    echo "Connecting $line"
    pw-link $line
done < <(cat -- "$1")
pw-dewire
#!/bin/bash

link_nodeOutput=''

while IFS= read -r line; do
    if [[ "$line" =~ [|] ]];
    then
        link_nodeInput=`echo $line | cut -d ">" -f 2`
        echo "Removing $link_nodeOutput, ${link_nodeInput//' '}"
        pw-link -d $link_nodeOutput ${link_nodeInput//' '}
    else
        link_nodeOutput="$line"
    fi
done < <(pw-link -lo)
Sharing audio devices with computers on the network
PipeWire supports sharing audio over the network using several mechanisms, including:
AES67
RTP
Apple Airplay
(without DRM features)
JACK (
netjack2
)
Roc
PipeWire Native RTP
PulseAudio's network protocol
Snapcast
The PipeWire wiki includes an
overview and comparison page
for the different network protocols.
The Pulse Tunnel method is described below. The PipeWire PulseAudio implementation supports
network streaming
. An easy way to share audio between computers on the network is to use the
Avahi
daemon for discovery. To enable this functionality,
install
the
pipewire-zeroconf
package.
Make sure that the
avahi-daemon.service
is running (and UDP port
5353
is open if using a
firewall
) on all computers that will be sharing audio.
Note
Some GUI volume managers hide network cards by default. (ex: in Plasma one has to "Configure Audio Volume..." and check "Show virtual devices".
To share the local audio devices load the appropriate modules on the host (make sure to use the local IP address):
$ pactl load-module module-native-protocol-tcp listen=
192.168.1.10
$ pactl load-module module-zeroconf-publish
Then load the discovery module on the clients:
$ pactl load-module module-zeroconf-discover
It is also possible to load the modules automatically by creating a dedicated configuration file. On the host:
/etc/pipewire/pipewire-pulse.conf.d/50-zeroconf-publish.conf (or ~/.config/pipewire/pipewire-pulse.conf.d/50-zeroconf-publish.conf)
pulse.cmd = [
    { cmd = "load-module" args = "module-native-protocol-tcp listen=
192.168.1.10
" }
    { cmd = "load-module" args = "module-zeroconf-publish" }
]
On the client:
/etc/pipewire/pipewire-pulse.conf.d/50-zeroconf-discover.conf (or ~/.config/pipewire/pipewire-pulse.conf.d/50-zeroconf-discover.conf)
pulse.cmd = [
    { cmd = "load-module" args = "module-zeroconf-discover" }
]
Streaming audio to an AirPlay receiver
It is possible to stream audio to a device that is posing as an
AirPlay Receiver
. To enable this functionality, load the
RAOP Discover module
:
$ pactl load-module module-raop-discover
It is also possible to load this module automatically by creating a dedicated configuration file:
/etc/pipewire/pipewire.conf.d/raop-discover.conf (or ~/.config/pipewire/pipewire.conf.d/raop-discover.conf)
context.modules = [
   {
       name = libpipewire-module-raop-discover
       args = { }
   }
]
Some speakers' AirPlay implementations (like Sonos AirPlay 2 speakers) may require opening up ports 6001 and 6002 for incoming UDP traffic on your source device.
Streaming audio machine to machine via Roc
Roc streaming
is a realtime audio network protocol with forward error correction. It is easy to setup, since Pipewire supports it by default.
First
install
the
pipewire-roc
package.
On target / host / DAC:
~/.config/pipewire/pipewire.conf.d/
context.modules = [
  { name = libpipewire-module-roc-source
    args = {
        local.ip = 0.0.0.0
        roc.resampler.backend = default
        roc.resampler.profile = default
        roc.latency-tuner.backend = default
        roc.latency-tuner.profile = default
        fec.code = default
        sess.latency.msec = 100
        local.source.port = 10001
        local.repair.port = 10002
        local.control.port = 10003
    }
  }
]
See
PipeWire documentation
for more options.
Note
This works very well for Raspberry Pi DACs with recent Raspberry Pi operating system releases.
On sender / client:
~/.config/pipewire/pipewire.conf.d/roc-sink.conf
context.modules = [
  { name = libpipewire-module-roc-sink
    args = {
        fec.code = default
        remote.ip = <IP address of host>
        remote.source.port = 10001
        remote.repair.port = 10002
        remote.control.port = 10003
        sink.props = {
            node.name = "my-roc-sink"
            node.description = "my-roc-sink"
        }
    }
  }
]
See
PipeWire documentation
for more options.
Note
node.description
sets the displayed name of the sink read by
pulsemixer
, while
node.name
is read by
pactl
. It is advisable to set both.
Restart
the
pipewire.service
user unit
on both machines.
Run PipeWire on top of native JACK
PipeWire can also run as a
JACK
client on top of the native JACK daemon if desired.
See
JACK and PipeWire (PipeWire wiki)
and
JACK Bridge (PipeWire wiki)
for more information and additional configuration (like available channels for example).
To use it install the
pipewire-jack-client
and start JACK. Pipewire should be bridged automatically.
Note
Since pipewire
0.3.81
loading the jackdbus module is done automatically and is no longer necessary.
It can manually be loaded (as explained by
pactl(1)
) like a PulseAudio module:
pactl load-module module-jackdbus-detect
before starting jack.
Use ALSA dmix devices as PipeWire sinks
It is possible to have a PipeWire server (or multiple, for each user) output to ALSA via
ALSA dmix devices
. This allows you to use ALSA as the primary audio output system while being able to use non-ALSA devices such as Bluetooth headphones.
ALSA dmix setup
Suppose you have two cards,
PCH
and
HDMI
:
/proc/asound/cards
0 [PCH            ]: HDA-Intel - HDA Intel PCH
                      HDA Intel PCH at 0xdff40000 irq 146
 1 [HDMI           ]: HDA-Intel - HDA ATI HDMI
                      HDA ATI HDMI at 0xdfe60000 irq 147
and your PCMs look like:
/proc/asound/pcm
00-00: ALC1220 Analog : ALC1220 Analog : playback 1 : capture 1
00-02: ALC1220 Alt Analog : ALC1220 Alt Analog : capture 1
01-03: HDMI 0 : HDMI 0 : playback 1
01-07: HDMI 1 : HDMI 1 : playback 1
01-08: HDMI 2 : HDMI 2 : playback 1
01-09: HDMI 3 : HDMI 3 : playback 1
01-10: HDMI 4 : HDMI 4 : playback 1
01-11: HDMI 5 : HDMI 5 : playback 1
and suppose your ALSA configuration looks something like this:
/etc/asound.conf
ctl.!default {
  type hw
  card PCH
}

pcm.!default {
  type plug
  slave.pcm "
dmix:PCH,0
"
}

pcm.dhdmi {
  type plug
  slave.pcm "
dmix:HDMI,9
"
}
In this particular example, the dmix devices would be
dmix:PCH,0
and
dmix:HDMI,9
.
PipeWire dmix setup
First of all, stop WirePlumber from monitoring and adding hardware ALSA devices by disabling the
monitor.alsa
feature:
/etc/wireplumber/wireplumber.conf.d/disable-alsa-monitor.conf (or ~/.config/wireplumber/wireplumber.conf.d/disable-alsa-monitor.conf)
wireplumber.profiles = {
  main = {
    monitor.alsa = disabled
  }
}
Now, configure PipeWire to use dmix devices. The default configuration file (
/usr/share/pipewire/pipewire.conf
) contains a
commented out example
which you can use as a basis.
Add your own element to the
context.objects
array:
/etc/pipewire/pipewire.conf.d/alsa-dmix.conf (or ~/.config/pipewire/pipewire.conf.d/alsa-dmix.conf)
context.objects = [
    # We do not start with dmix, but with an input device.
    # Do not forget to add an input device.
    # On a friend's Laptop, I saw Zoom having a nervous
    # breakdown and endlessly crying because no input device
    # was configured! You have been warned.
    { factory = adapter
        args = {
            factory.name           = api.alsa.pcm.source
            node.name              = "alsa-mic-internal" # name of pulse device (mpv)
            node.description       = "Mic Internal" # name of pulse device (pavucontrol)
            media.class            = "Audio/Source"
            api.alsa.path          = "
hw:PCH,0
"
        }
    }
    # Okay, now we add our dmix PCMs
    { factory = adapter
        args = {
            factory.name           = api.alsa.pcm.sink # sink for dmix
            node.name              = "alsa-dmix-internal" # name of pulse device (mpv)
            node.description       = "PCM Internal" # name of pulse device (pavucontrol)
            media.class            = "Audio/Sink" # Sink for dmix
            api.alsa.path          = "
dmix:PCH,0
"
        }
    }

    { factory = adapter
        args = {
            factory.name           = api.alsa.pcm.sink # sink for dmix
            node.name              = "alsa-dmix-hdmi" # name of pulse device (mpv)
            node.description       = "PCM HDMI" # name of pulse device (pavucontrol)
            media.class            = "Audio/Sink" # Sink for dmix
            # remember this is a non-default dmix from /etc/asound.conf
            api.alsa.path          = "
dmix:HDMI,9
"
        }
    }
]
As a user (non-root), check out the output of
wpctl status
, and set the default input(source) and output(sink) devices to your liking with
wpctl set-default
ID
.
ID
is the number before sink/source names.
Now, you can fully test your configuration.
Switching between device profiles
Some hardware audio devices, like
snd_hda_intel
, function differently depending on which profile the device is running in. In the case of
snd_hda_intel
, there are separate profiles for HDMI and analog output.
Switching to HDMI with WirePlumber:
$ wpctl set-profile <device-ID> 3
$ wpctl status
...
├─ Sinks:
│  *   53. Built-in Audio Digital Stereo (HDMI) [vol: 1.00]
...
Switching to analog with WirePlumber:
$ wpctl set-profile <device-ID> 1
$ wpctl status
...
├─ Sinks:
│  *   51. Built-in Audio Analog Stereo        [vol: 0.60]
...
Multi-user audio sharing
Sometimes it is useful to let other users connect to your PipeWire instance. For example, if you login into a different user's account using
Xephyr
and want the audio you play in the Xephyr session to come out the speakers which are managed by the outer user.
One method to do this is to configure the outer user's pipewire-pulse config to listen for localhost tcp connections.
Create a file like under the outer user's home directory:
~/.config/pipewire/pipewire-pulse.conf.d/pulse-server.conf
pulse.properties = {
    server.address = [
        "unix:native"
        "tcp:127.0.0.1:4713"   # Now the outer user's pipewire server listens on the IP4 loopback
    ]
}
Then set the environment variable
PULSE_SERVER=tcp:127.0.0.1:4713
in the inner user's session. For example,
export
ing it before you start
Xephyr
as the inner user. More information and alternative setups can be found on
this forum thread
.
WebRTC screen sharing
Most applications used to rely on X11 for capturing the desktop (or individual applications), for example when using WebRTC in web browsers (e.g. on Google Meet). On Wayland, the screen sharing mechanism is handled through the
XDG Desktop Portal
and PipeWire, which enables sharing content under Wayland with fine-grained access controls.
Tip
Test whether WebRTC screen sharing is working by using
Mozilla's GetUserMedia WebRTC test page
.
Note
xdg-desktop-portal
1.10.0 fixed a mismatch between specification and implementation of its D-Bus interface.
[2]
Hence, some clients may not work with xdg-desktop-portal 1.10.0 or newer.
Firefox (84+) and Chromium (110+) support this method by default, while on older versions of Chromium (73+), one needs to enable
WebRTC PipeWire support
by setting the corresponding (experimental) flag at the URL
chrome://flags/#enable-webrtc-pipewire-capturer
or via CLI argument
--enable-features=WebRTCPipeWireCapturer
.
obs-studio
(27+) supports this method by using the new PipeWire capture source.
Video
This article or section needs expansion.
Reason:
pipewire-v4l2
(Discuss in
Talk:PipeWire
)
Although the software is not yet production-ready, it is safe to play around with. Most applications that rely on
GStreamer
to handle e.g. video streams should work out-of-the-box using the PipeWire GStreamer plugin, see
GStreamer#PipeWire
. Applications like e.g.
cheese
AUR
are therefore already able to share video input using it.
Using
pipewire-v4l2
, it should also be possible to use the
pw-v4l2
script to preload a library (
/lib/pipewire-0.3/v4l2/libpw-v4l2.so
) that intercepts v4l2 calls and routes video through pipewire.
Audio post-processing
Pipewire module-filter-chain
Pipewire has an internal module called
filter-chain
that can create nodes to process audio input and output. See
/usr/share/pipewire/filter-chain/
for examples including equalization, virtual surround sound, LADSPA plugins and channel mixing.
LADSPA
You can install many LADSPA plugins from the official repositories and use them in Pipewire filter chains.
To list plugin labels and available controls provided by a specific file use
analyseplugin
from the
ladspa
package:
$ analyseplugin /usr/lib/ladspa/lsp-plugins-ladspa.so
Systemwide parametric equalization
PipeWire filter-chain supports Parametric EQ
[3]
. Create a config file inside
/etc/pipewire/pipewire.conf.d/
(or
~/.config/pipewire/pipewire.conf.d/
), then edit it to incorporate desired parameters using the following example:
context.modules = [
    {
        name = libpipewire-module-filter-chain
        args = {
            node.description = "Equalizer Sink"
            media.name       = "Equalizer Sink"
            filter.graph = {
                nodes = [
                    {
                        type  = builtin
                        name  = eq
                        label = param_eq
                        config = {
                            filters = [
                                { type = bq_peaking, freq = 100, gain = 0.0, q = 1.0 },
                                { type = bq_peaking, freq = 500, gain = 0.0, q = 1.0 },
                                { type = bq_peaking, freq = 2000, gain = 0.0, q = 1.0 },
                            ]
                        }
                    }
                ]
                links = []
            }
            audio.channels = 2
            audio.position = [ FL FR ]
            capture.props = {
                node.name   = "effect_input.eq"
                media.class = Audio/Sink
            }
            playback.props = {
                node.name   = "effect_output.eq"
                node.passive = true
            }
        }
    }
]
You can use arbitrary amount of filters.
If you require a pre-amp, apply a
bq_highshelf
filter at frequency 0, for example:
{ type = bq_highshelf, freq = 0, gain = -5.0, q = 1.0 },
Restart Pipewire, select "Equalizer Sink" as your default sound output device; this should then apply to all applications.
Alternatively, instead of specifying the
filters
array, you can provide a
filename
property, pointing to a parametric equalizer configuration generated from the
AutoEQ
project or
Squiglink
, like:
config = {
    filename = "/path/to/parametric.txt"
}
EasyEffects
EasyEffects (formerly
PulseEffects
) is a Qt utility which provides a large array of audio effects and filters to individual application output streams and microphone input streams. Notable effects include an input/output equalizer, output loudness equalization and bass enhancement, input de-esser and noise reduction plug-in. See
the GitHub page
for a full list of effects.
Note
Firefox has an issue with microphone stream, see
GitHub issue
.
In order to use EasyEffects, install
easyeffects
. See
Community Presets
for a collection of preset configurations. See
AutoEq
for collection of algorithmically generated EQ presets for headphones.
Note
EasyEffects may crash after starting, throwing GTK errors, see
GitHub issue
for a workaround.
NoiseTorch
NoiseTorch is an alternative way for noise suppression, packaged with
noisetorch
AUR
. There also exists
noisetorch-git
AUR
.
After starting it the module can be loaded for the selected microphone. It is possible to adjust the voice activation threshold, which should be set to the highest level, not filtering out any actual voice.
You can start audio processing with systemd automatically, see
[4]
. Note that the noisetorch binary path is different if installed from AUR.
Noise suppression for voice
Install
the
noise-suppression-for-voice
package.
You may follow the instructions given on
GitHub
.
Note
If following the instructions above and since PipeWire
1.4.10
, you may need to specify that your audio input is Mono. You can do this by adding the following 2 lines to the end of both the
capture.props
and
playback.props
sections of your config:
~/.config/pipewire/pipewire.conf.d/99-input-denoising.conf
audio.channels = 1
audio.position = [ MONO ]
JamesDSP
JamesDSP for Linux
(available as
jamesdsp
AUR
) provides open-source sound effects for PipeWire and PulseAudio. It uses its own effects engine and without depending on LADSPA, Calf, etc. JamesDSP was initially published as an audio effects processor for Android devices.
Using LADSPA, LV2 and VST plugins
If you want to choose between the full list of available LADSPA, LV2 and VST plugins, you can apply them using
carla
with
pipewire-jack
.
Start Carla and go to
Settings > Configure Carla > Engine
. Make sure
Audio driver
is set to
JACK
and choose a
process mode
depending on your needs. You can also choose the process mode by running Carla with a specific command, for example
carla-rack
for the
Continuous Rack
mode.
You can connect application outputs to Carla manually, but if you want to pass multiple applications through Carla, it might be more convenient to create a single virtual device between applications and Carla and optionally use it as a default device. At the begin, create a new null sink named
default_null_sink
.
/etc/pipewire/pipewire.conf.d/10-default-null-sink.conf (or ~/.config/pipewire/pipewire.conf.d/10-default-null-sink.conf)
context.objects = [
  {
    factory = adapter
    args = {
      factory.name = support.null-audio-sink
      node.name = "default_null_sink"
      media.class = Audio/Sink
      audio.position = [ FL FR ]
      monitor.channel-volumes = true
      monitor.passthrough = true
    }
  }
]
Restart PipeWire to apply changes.
Alternatively, you can create a temporary virtual device with
pw-cli(1)
or, if
pipewire-pulse
is installed, with
pactl(1)
. See
the PipeWire wiki
for details.
In the
Rack
tab, add whichever plugin you want. Make sure they are
stereo
type. You can change their order. In the
Continuous Rack
process mode, the one on top of the list will be the first to receive the audio stream, just like in EasyEffects. Afterwards go to the
Patchbay
tab and connect the
default_null_sink
L/R monitors to Carla inputs, then Carla outputs to the playbacks of your desired device (speakers, earphones, HDMI, etc). Save the configuration to a local file, for example
~/Documents/carla_sink_effects.carxp
. Carla will automatically restore the connections after opening this file.
You can test the effects while a multimedia application is reproducing audio, i.e. watching a video on a website through Firefox. There are two methods to do it. The first one, inside Carla
Patchbay
tab, disconnecting all Firefox connections and linking its L/R outputs to
default_null_sink
playbacks. The second through
pavucontrol
, locating Firefox audio stream and redirecting it to
default_null_sink
(this should remember the connection to automatically redirect the application to the same sink on the next instance).
To run Carla with the
Continuous Rack
process mode and load the saved file at startup, create a
systemd user service
:
~/.config/systemd/user/jack-carla-rack.service
[Unit]
Description=Load Carla Rack JACK host

[Service]
Environment=PIPEWIRE_LINK_PASSIVE=true
Type=exec
ExecStart=/usr/bin/carla-rack --no-gui %h/Documents/carla_sink_effects.carxp

[Install]
WantedBy=default.target
Then
enable
the
jack-carla-rack.service
user unit
.
Note that if you set the
default_null_sink
as the default device in system settings, all applications will be redirected to it and the volume keys will change its level, not the one on the speakers. If you want to control volume speakers, leave them as the default in system settings and redirect your desired application to
default_null_sink
inside pavucontrol (Pipewire compatibility layer will remember the connection on the next instance of the same application).
Troubleshooting
This article or section is a candidate for merging with
PipeWire/Troubleshooting
.
Notes:
This section is long enough to be split into a dedicated subpage. (Discuss in
Talk:PipeWire#Move Troubleshooting into a new separate page
)
Audio
Microphone is not detected by PipeWire
If you are using a built in microphone of a laptop, or connected using the headphone jack: First make sure the analog input is enabled in the profile in use. You can check the profile in
pavucontrol
(and possibly in your desktop environment sound settings). In pavucontrol, on the Configuration tab, under "Built-in Audio" (or similar) make sure "Analog Stereo Duplex" is selected. If you use an advanced sound setup such as 5.1 or sound over HDMI, make sure a profile that includes "+ Analog Stereo Input" is selected.
PipeWire's
alsa-monitor
module uses
alsa-card-profiles
to detect devices by default. If this is not working for you, try to turn off
api.alsa.use-acp
, or optionally turn on
api.alsa.use-ucm
in
wireplumber
:
/etc/wireplumber/wireplumber.conf.d/alsa-config.conf (or ~/.config/wireplumber/wireplumber.conf.d/alsa-config.conf)
monitor.alsa.properties = {
  # Use ALSA-Card-Profile devices. They use UCM or the profile
  # configuration to configure the device and mixer settings.
# alsa.use-acp = true
# Use UCM instead of profile when available. Can be disabled
  # to skip trying to use the UCM profile.
alsa.use-ucm = true
}
With
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
...
Then, restart WirePlumber and check available devices:
This article or section is out of date.
Reason:
Option
--list-targets
is no longer available in the recent versions of
pw-record
; in order to list objects use either
wpctl status
or
pw-cli ls
or
pw-dump
instead. (Discuss in
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
An alternative solution suggested in
this PipeWire issue
is to add the microphone manually. First of all, make sure the microphone is detected by ALSA.
$ arecord -l
**** List of CAPTURE Hardware Devices ****
card
card_number
:
card_name
, device
device_number
:
device_name
...
Choose your microphone from the list, and to further test the microphone, run the following commands.
$ arecord --duration=5 --format=dat --device=hw:
card_number
,
device_number
test-mic.wav # record from the mic
$ aplay test-mic.wav # play it
If the microphone is working with
arecord
, but not detected by PipeWire, try to add a config file to manually add this device.
/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       = "Undetected Microphone"
            media.class            = "Audio/Source"
            api.alsa.path          = "hw:
card_number
,
device_number
"
        }
    }
]
And then restart PipeWire to reload the config.
Sound does not automatically switch when connecting a new device
To automatically switch to newly connected devices, create this file:
/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" }
]
Then
restart
the
pipewire-pulse.service
with
systemctl --user
and check that
module-switch-on-connect
is loaded.
No sound after connecting to Bluetooth device
As of 2020-12-07, if there is no sound after connecting a Bluetooth device, you might need to switch the default sink and/or move a sink input to the correct sink. Use
pactl list sinks
to list the available sinks and
pactl set-default-sink
to switch the default sink to the Bluetooth device. This can be automated via
udev
using a script similar to
this one
.
See this
Reddit thread
for a discussion of the issue. According to author of the script, the headset profile (HSP) might still have problems.
No sound in mpv, vlc, totem, but sound works in web browser and GNOME speaker test
The factual accuracy of this article or section is disputed.
Reason:
The writing style is not wiki, but more like a blog. It needs a rephrase + shortening. Sub chapters are overkill as well. Issue root cause is guessed not verified.  (Discuss in
Talk:PipeWire
)
Condition description
The best tool to verify the condition of this issue is to use
mpv
on a file that is expected to work with installed codecs:
$ 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
This recipie applies if some or all of the above tests produce sound and the same test with
pipewire
option does not produce sound:
$ mpv --ao=pipewire
test_file.mpv
Gnome desktop speaker test and web browser 'youtube' produce valid sound outcomes.
Switching inputs, muting, unmuting, changing volume in Gnome does not resolve the issue.
Sink status reported by
pactl list sinks
as 'SUSPENDED' is of no concern, because status properly changes when running video through a web browser.
Use of
pactl info
does not point to any obvious issues.
Inspection of relevant
systemd
unit logs does not point to any obvious issues.
Reason for the issue
It seems that a path from
pipewire
to hardware got muted or changed somehow.  The original author does not know how to identify and point out at the issue using command line tooling.
Solution
Install
the
pavucontrol
package.  Run
pavucontrol
, select the appropriate source in the Configuration tab,  select it again in the Output device tab and then use Mute button to mute and unmute the source while
mpv --ao=pipewire test.mp4
video is running.
In another case, removing
~/.local/state/wireplumber/
and rebooting solved the same problem.
Low volume
After replacing PulseAudio with Pipewire, sound may work fine, but after a reboot, the volume becomes intolerably low.
Open
alsamixer
, use
F6
to select the proper soundcard, and make sure the ALSA volumes are at 100%.
alsactl
should maintain this setting after reboot.
Increasing 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
Install
realtime-privileges
and add your own user to the
realtime
group.
Alternatively, increasing memlock from 64kB to 128kB seems enough to fix this. If you are running
pipewire-pulse
under
systemd/User
, add:
username	soft	memlock	64
username	hard	memlock	128
to
/etc/security/limits.d/username.conf
Changing the default sample rate
By default PipeWire sets a fixed global sample rate of 48kHz. If you need to change it, you can set a new default (although it isn't recommended):
/etc/pipewire/pipewire.conf (or ~/.config/pipewire/pipewire.conf)
...
context.properties = {
    ...
default.clock.rate          =
sample_rate
...
This, however, isn't recommended as this will affect latencies as the quantum values aren't re-calculated automatically. You will have to change these yourself if you want to preserve the same ratio. To quote the documentation:
The default clock rate determines the real time duration of the min/max/default quantums. You might want to change the quantums when you change the default clock rate to maintain the same duration for the quantums.
Keep in mind that the rates of the streams will remain the same. All that PipeWire will be doing here is resampling to meet your new rate. So the 48kHz streams that would've been left unaltered will now be resampled.
If you have gear that can handle different sample rates, it is instead recommended to leave the defaults and follow as indicated here:
#Changing the allowed sample rate(s)
Changing the allowed sample rate(s)
PipeWire can also change dynamically the output sample rates supported by your DAC. The sample rate follows the sample rate of the audio stream being played.
/etc/pipewire/pipewire.conf (or ~/.config/pipewire/pipewire.conf)
...
context.properties = {
    ...
default.clock.allowed-rates = [
sample_rate_1
sample_rate_2
sample_rate_3
... ]
...
for example,
[ 44100 88200 176400 48000 96000 192000 ]
.
Say the default sample rate is
48000
, which is the default. Normally if a stream outputs audio at 44100Hz (i.e. a music player playing a song at CD quality), Pipewire will resample the stream to 48kHz. However, if you have
44100
in this list, Pipewire will instead do the following. Pipewire will see that the stream is at 44100Hz, then check if
44100
is in the allowed rates and that the receiving output device (i.e. DAC) supports the rate.
In such case, the DAC will play the song losslessly.
If the rate isn't in the list or if the DAC doesn't support the rate, PipeWire will simply fall back to resampling the stream to the default sample rate.
According to
the developer
: "PipeWire allows up to 16 different sample rates and will switch when possible". That means, with configuration above,
no resampling is done
when supported. Since PipeWire
0.3.61
up to 32 different sample rates can be configured.
Getting allowed sample rate(s)
Consult your hardware manual for supported values of your DAC. Supported rates by the kernel driver codec are listed with the following command.
$ grep -E 'Codec|Audio Output|rates' /proc/asound/card*/codec#*
If your DAC does not report codec information, you can try to obtain supported rates like this:
$ grep -m1 -Hn "" /proc/asound/card?/stream? | tee /dev/tty | awk -F':' '{print $1}' | xargs grep 'Rates'
Note
Although your DAC chip may report rates higher than advertised in specification, some of them were designed for exotic modes like USB to I2S
Checking currently used sample rate
To check which output sample rate is being used for a card run:
$ grep rate: /proc/asound/card?/pcm??/sub?/hw_params
/proc/asound/card1/pcm0p/sub0/hw_params:rate: 96000 (96000/1)
In
pcm0p
or
pcm0c
c
is short for "capture" and
p
is for "playback".
Command:
$ pw-top
also shows currently used sample rate for each card and audio stream.
Tip
If your DAC will not switch to a higher rate, after setting default.clock.allowed-rates, it may mean that system cannot read rates supported by DAC. In such case you can still try setting default.clock.rate
Sound quality
Lossless
Lossless output (no resampling) is easy to configure with PipeWire. All you should have to do is set the following, which is described here:
#Changing the allowed sample rate(s)
. Read that section for further context. These are the industry standard rates that you'll encounter, being the CD quality family (44100Hz, 88200Hz, 176400Hz) and DVD quality family (48kHz, 96kHz, 192kHz). Most audio streams will be in one of these rates. As long as your player of choice is the main stream, and your DAC supports the rate, PipeWire will use it.
Ensure that your player is the only stream playing or resampling may occur as everything else is resampled to match the sample rate of the main graph.
/etc/pipewire/pipewire.conf (or ~/.config/pipewire/pipewire.conf)
...
context.properties = {
    ...
default.clock.allowed-rates = [
44100
88200
176400
48000
96000
192000
]
...
Resampling
If you used PulseAudio with
resample-method = speex-float-10
or
soxr-vhq
, then you might consider setting
resample.quality
to
10
or the maximum
14
:
/etc/pipewire/client.conf.d/resample.conf (or ~/.config/pipewire/client.conf.d/resample.conf)
stream.properties = {
    resample.quality = 10
}
Do not forget to
restart
the
pipewire.service
and
pipewire-pulse.socket
user units
(never forget
pipewire-pulse.socket
if you want your configuration changes to be applied).
There is a very little quality difference between
10
and
14
, but the CPU load difference is 2-3x. And the latency difference between
4
,
10
,
14
is yet to be investigated by anybody.
resample.quality = 14
on 44100→48000 Hz on Ryzen 2600 causes
pipewire
or
pipewire-pulse
processes to cause 4.0% one CPU core load.
You can compare resamplers here:
https://src.infinitewave.ca/
(do not pay attention to anything above 18 KHz and over 120 dB). speex is listed as "Xiph.org Speex".
PipeWire uses its own resampling algorithm called Spa. Like with SoX's
sox
, Speex's
speexenc
, PipeWire includes its standalone version:
spa-resample
. Usage:
$ spa-resample -q 14 -f s24 -r 48000 input16bit44100orAnythingElse.wav output24bit48000hz.wav
It is probably somehow possible to use other resamplers by creating your own sink. Or just use a plugin in your music player (e.g., Qmmp has SoX plugin).
External sound card not activated after reconnect
Check
~/.config/pipewire/media-session.d/default-profile
if there is any entry with default profile "off" and remove it. If that does not help, remove all files from
~/.config/pipewire/media-session.d/
and
restart
the
pipewire.service
user unit
.
No Sound or pactl info shows Failure: Connection refused
It means applications are unable to connect to the PipeWire-Pulse service check if the
pipewire-pulse.service
user unit
is running.
If that does not fix it, run
strace -f -o /tmp/pipe.txt pactl info
and pastebin
/tmp/pipe.txt
while seeking help on IRC (
#pipewire
on OFTC) or the mailing-lists.
Low audio quality on Bluetooth
In case Bluetooth playback stutters, check the
unit status
of the
pipewire.service
user unit for errors similar as below:
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
If they appear, check the currently selected codec using
pactl list sinks
and try changing it by setting
bluez5.codec
to one of
sbc aac ldac aptx aptx_hd
. You can also try mSBC support (fixes mic on Sony 1000XM3, i.e. Headphones WH-1000XM3 and Earbuds WF-1000XM3), and the SBC-XQ codec.
Note
Headphones like the WH-1000XM3 refuse to advertise any codecs other than SBC/SBC-XQ if "Sound Quality Mode" is set to "Priority On Stable Connection" instead of "Prioritize Sound Quality" in the companion app.
With
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 ]
}
With
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]
...
Restart PipeWire by
restarting
the
pipewire.service
user unit for the changes to take effect.
Noticeable audio delay or audible pop/crack when starting playback
This is caused by node suspension when inactive.
With
wireplumber
, create a new file to overwrite the default configuration:
/etc/wireplumber/wireplumber.conf.d/disable-suspension.conf (or ~/.config/wireplumber/wireplumber.conf.d/disable-suspension.conf)
monitor.alsa.rules = [
  {
    matches = [
      {
        # Matches all sources
        node.name = "~alsa_input.*"
      },
      {
        # Matches all sinks
        node.name = "~alsa_output.*"
      }
    ]
    actions = {
      update-props = {
        session.suspend-timeout-seconds = 0
      }
    }
  }
]
# bluetooth devices
monitor.bluez.rules = [
  {
    matches = [
      {
        # Matches all sources
        node.name = "~bluez_input.*"
      },
      {
        # Matches all sinks
        node.name = "~bluez_output.*"
      }
    ]
    actions = {
      update-props = {
        session.suspend-timeout-seconds = 0
      }
    }
  }
]
Restart
pipewire.service
and
wireplumber.service
to apply changes.
Instead of disabling suspension entirely, you can also change the timeout value to the desired number of seconds of delay before source suspension.
Some devices implement their own detection of silence and suspension. For them disabling node suspention alone won't work. It's possible to work around them by adding a small amount of noise, making it so the output never goes fully silent:
.../disable-suspension.conf
...
    session.suspend-timeout-seconds = 0,  # 0 disables suspend
    dither.method = "wannamaker3", # add dither of desired shape
    dither.noise = 2, # add additional bits of noise
...
It may be necessary to play with
dither.noise
and
dither.method
parameters to make it so the noise is sufficiently silent and simultaneously loud enough to prevent detection of silence. See
PipeWire documentation
.
With
pipewire-media-session
:
Disable this by editing
/etc/pipewire/media-session.d/*-monitor.conf
depending on where the delay occurs and changing property
session.suspend-timeout-seconds
to 0 to disable or experiment with other values and see what works.
Alternatively you can comment out the line
suspend-node
in
/etc/pipewire/media-session.d/media-session.conf
.
Restart
both
pipewire.service
and
pipewire-pulse.service
to apply these changes, or alternatively reboot.
Audio cutting out when multiple streams start playing
This problem can typically be diagnosed by reading the
journal
of the
pipewire-pulse.service
user unit
and finding lines similar to:
pipewire-pulse[21740]: pulse-server 0x56009b9d5de0: [Nightly] UNDERFLOW channel:0 offset:370676 underrun:940
According to the
official PipeWire troubleshooting guide
, to solve this problem for
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
      }
    }
  }
]
With
pipewire-media-session
:
/etc/pipewire/media-session.d/alsa-monitor.conf (or ~/.config/pipewire/media-session.d/alsa-monitor.conf
api.alsa.headroom = 1024
If you experience audio stuttering because of kernel page locking or late scheduling see
Gaming#Tweaking kernel parameters for response time consistency
.
Audio is distorted
For microphones, try navigating to the card that is having issues after running
alsamixer
and use the arrow keys to reduce any "Mic Boost" or "Internal Mic Boost" options.
Follow
#Changing the default sample rate
, reducing the sample rate to
44100
(44.1 kHz).
Audio problems after standby
If the sound is missing or otherwise garbled after waking the machine up from sleep, it might help to reinitialize ALSA:
# alsactl init
High latency with USB DACs (e.g. Schiit DACs)
Changing sample rates or formats might help reduce latency with some DACs such as Schiit Hel 2.
[5]
For
pipewire-media-session
:
Copy the default configuration file
/usr/share/pipewire/media-session.d/alsa-monitor.conf
into
/etc/pipewire/media-session.d/
(or
~/.config/pipewire/media-session.d/
).
Then append a new rule-block similar to the following one:
/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
                # Following value should be doubled until audio does not cut out or other issues stop occurring
                api.alsa.period-size = 128
...
For
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
        # Following value should be doubled until audio does not cut out or other issues stop occurring
        api.alsa.period-size = 128
      }
    }
  }
]
alsa_output.
name-of-node
node can be obtained using
pw-top
.
Your DAC might support a different format or sample rate. You can check what your DAC supports by querying
ALSA
:
First get the card number of your DAC:
$ aplay -l
...
card 3: S2 [Schiit Hel 2], device 0: USB Audio [USB Audio]
  Subdevices: 0/1
  Subdevice #0: subdevice #0
...
So in this example it would be card 3.
Get all supported sample rates and formats:
$ cat /proc/asound/card
X
/stream
X
...
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
    ...
...
In this case
S16_LE, S24_3LE, S32_LE
are the supported formats and
44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000
are the supported sample rates across all formats.
No sound from USB DAC until 30% volume
Some USB DACs will have no sound output until a certain level of volume is reached
[6]
. Typically, this is around 15% to 30%, which may result in an uncomfortably loud initial volume and the inability to maintain a low volume. The solution is to ignore hardware mixer volume control by setting
api.alsa.soft-mixer
for the device to
true
.
To achieve this with
wireplumber
, use:
/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 = {
        # Do not use the hardware mixer for volume control. It
        # will only use software volume. The mixer is still used
        # to mute unused paths based on the selected port.
        api.alsa.soft-mixer = true
      }
    }
  }
]
Refer to
WirePlumber#Obtain interface name for rules matching
to find the correct value to replace
"alsa_card.
name-of-device
"
.
Alternatively, you may specify
"~alsa_card.*"
to apply the rules to all your audio devices.
Then, restart pipewire, e.g. by running
systemctl --user restart pipewire
. Set your master volume in
alsamixer
, then save the settings by running
alsactl store
as root. You should now be able to use your volume mixer as normal.
Realtime audio does not work
If
RTKit error: org.freedesktop.DBus.Error.AccessDenied
shows up in the
status
of the
pipewire.service
user unit
, then the priority of the pipewire daemon was not changed to realtime. See
[7]
for this issue.
Simultaneous output to multiple sinks on the same sound card
Create a copy of
/usr/share/alsa-card-profile/mixer/profile-sets/default.conf
so that changes persist across updates. Here we define a profile joining the two default mappings for Analog and 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 = Digital Stereo (HDMI)
device-strings = hdmi:%f
paths-output = hdmi-output-0
channel-map = left,right
priority = 9
direction = output

[Profile multiple]
description = Analog Stereo Duplex + Digital Stereo (HDMI) Output
output-mappings = analog-stereo hdmi-stereo
input-mappings = analog-stereo
Then configure your session manager to use the new card-profile for matching devices. Identifying information can be found using
pw-dump
or
wpctl
.
For
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"
      }
    }
  }
]
For
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
            }
        }
    }
]
No notification sounds from Discord
This might cause by having the min.quantum too low, try setting it to more than 700. You can make an override for Discord specifically by appending the following rule to the pulse.rules section of pipewire-pulse.conf.
/etc/pipewire/pipewire-pulse.conf (or ~/.config/pipewire/pipewire-pulse.conf)
...
pulse.rules = [
  ...
    {
        # Discord notification sounds fix
        matches = [ { application.process.binary = "Discord" } ]
        actions = {
            update-props = {
                pulse.min.quantum      = 1024/48000     # 21ms
            }
        }
    }
...
FMOD games crashing under PipeWire
Some games that use an old version of the
FMOD audio engine
, like
Pillars of Eternity
, invoke
pulseaudio --check
and crash if the PulseAudio binary is not present. A workaround is to symlink
/bin/pulseaudio
to
/bin/true
.
[8]
# ln -s /bin/true /bin/pulseaudio
Note that if you wish to reinstall PulseAudio, you need to remove the symlink.
Auto-switching is not working
If auto-switching is not working it may be an issue with
WirePlumber
state. As suggested by
this comment
you can delete
WirePlumber
's local state and restart the daemon to see if that helps:
$ rm -r ~/.local/state/wireplumber/
Then
restart
the
wireplumber.service
user unit
.
Missing realtime priority/crackling under load after suspend
Due to a
bug from 2011
in rtkit, suspend events cause PipeWire's realtime priority to be revoked and not restored. To disable the protection which causes this,
edit
rtkit-daemon.service
:
/etc/systemd/system/rtkit-daemon.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/lib/rtkit-daemon --no-canary
Then restart the
rtkit-daemon.service
unit and
pipewire.service
user unit, along with the media session service.
No sound during streaming to RAOP devices (Sonos etc.)
Set up mDNS hostname resolution using either
Avahi
or
systemd-resolved
.
No sound devices show up in KDE Plasma
PipeWire clients (including the desktop environment) may rely on the
XDG_RUNTIME_DIR
environment variable
to connect to the PipeWire daemon.
[9]
If you experience no sound devices immediately after login, it may be because this variable has manually been set to the wrong path.
Although this be resolved by manually restarting PipeWire, other issues can still occur such as being unable to screen share in Chromium (with
pipewire context failed
).
XDG_RUNTIME_DIR
is automatically set by
pam_systemd(8)
, so you should remove any instances of it being set in your initialization files.
Device volume for SDDM and LightDM users is not restored on login
If you use
SDDM
or
LightDM
and notice that your audio volume level is not properly restored after logging in, mask PipeWire for the display manager's user, since WirePlumber running under the display manager can interfere with your user's WirePlumber session.
# systemctl --user -M
user
@ mask pipewire.socket
Replace
user
with
sddm
for SDDM or
lightdm
for LightDM.
For more details, see this
Debian Wiki article
.
Terminal bell not working
From PipeWire's perspective, one must have the module x11.bell loaded. This shall be the configuration default (see also in config files mentioned above). Check if you have package
pipewire-x11-bell
installed. Also, your window manager might influence the terminal bell, e.g., for xfwm, check in the xfwm-terminal settings that "Audible bell" is activated. Now, restart pipewire service:
$ systemctl --user restart pipewire
You can try if the terminal bell works with:
$ echo $'\a'
No sound until after first playback attempt
When PipeWire is started using socket activation, some PipeWire-native applications may attempt to play audio before
WirePlumber
configures the nodes, resulting in an error, for example:
$ 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
As a workaround, you can
enable
the
pipewire.service
user unit
.
Video
OBS (etc.) display nothing, even if they ask for a window/screen
If you are sure that you have
xdg-desktop-portal
installed as well as either
xdg-desktop-portal-gtk
or
xdg-desktop-portal-kde
, check the running state of the daemons.
In OBS, if everything is working, you should see this in
stdout
:
...
info: [pipewire] desktop selected, setting up screencast
info: [pipewire] created stream 0x5632d7456850
info: [pipewire] playing stream…
For multi-monitor setups the
slurp
package will allow to capture of all the screens.
See also
Wiki
— PipeWire Wiki on Freedesktop GitLab
Pipewire Update Blog Post
— Blog post from January 2018 outlining the state of PipeWire at the time
PipeWire Late Summer Update 2020
— Blog post from September 2020