Difficulty: ★★☆☆☆
This tutorial will help you get rid of crackling/popping issues in PipeWire and PipeWire-Pulse.
Edit: The guide now assumes that you are using wireplumber, pipewire-media-session instructions removed.
Tips:
Click to expand
-
In the vast majority of PipeWire crackling cases, it occurs in applications designed for PulseAudio, which is why you can (and should) generally solve these issues with PipeWire’s Pulse specific options and variables.
-
Try using ALSA without PulseAudio or PipeWire and see if you still have issues on ALSA (if you do, it’s unlikely that any setting you set in PipeWire is going to solve the issue) if you are using PipeWire and want to switch to ALSA, the command to stop Pipewire is:
systemctl --user stop pipewire.socket
-
The command to restart PipeWire is:
systemctl --user restart pipewire pipewire-pulse wireplumber
-
PipeWire has it’s own wiki that contains a lot of useful information., the alsa buffer page may be of particular interest, and covers content not in this guide.
-
So does wireplumber, the alsa page should be of particular interest.
-
Run
inxi -A
to confirm that you are running PipeWire and not pulse, it should output something like:
Audio: Device-1: Intel Cannon Lake PCH cAVS driver: snd_hda_intel Device-2: NVIDIA TU106 High Definition Audio driver: snd_hda_intel Sound Server-1: ALSA v: k5.14.2-1-MANJARO running: yes Sound Server-2: PipeWire v: 0.3.35 running: yes
With the PipeWire version being whatever version you happen to be running. If Pulseaudio is shown to be running then you are not using pipewire even if it says pipewire is running.
-
Run
pw-top
to see all open audio streams (can be useful to double check if an application is ignoring your settings)
-
QUANT = Quantum = Latency = Buffer Size.
Quantum divided by clock rate equals latency in seconds
(E.G. 1024/48000=0.02s or 21ms) -
Worst case scenario for below settings is setting the system’s minimum latency to ~40ms, this is not good for professional audio, but it is perfectly solid for consumer audio. In most cases though you will only have ~20ms min latency which is a lot better.
-
The default max latency in PipeWire is 170ms (8192/48000), it is probably safe to reduce to 85ms (4096/48000) which is still an acceptable latency for consumer audio, but wait with that until after you solve your initial crackling problem first.
-
For reference, standard audio on Windows, DirectSound normally has around 50-80ms latency. (WASAPI has around 10-30ms latency, ASIO has 1-10ms)
-
You can use
pw-metadata
to force a system-wide clock rate or quantum setting with:pw-metadata -n settings 0 clock.force-rate pw-metadata -n settings 0 clock.force-quantum
(where
0
is the id of your sound card, you can see the IDs of all PipeWire detected sound cards by running the command without arguments), this can be quite useful to test different latency and frequency settings on the fly. -
If you are unsure whether your application is using pipewire or pipewire-pulse, you can combine the commands to set the sound buffer size like so:
PULSE_LATENCY_MSEC=83 PIPEWIRE_LATENCY=1024/48000 <COMMAND>
You could set the above as a bash alias or even make it a bash script:
#!bin/sh PULSE_LATENCY_MSEC=83 PIPEWIRE_LATENCY=1024/48000 "$@"
which you can use so you do not have to type or remember the values every single time, this might be helpful if you find yourself using this a lot (the script approach could be very handy for steam games, because if you place the script under /usr/bin/ you can very use it as a launch option without using the full path).
Short Guide:
A much less detailed version of this guide meant for people who more or less know what they’re doing, but are feeling too lazy to be thorough about troubleshooting the issue. The full guide has better potential solutions, but this is the best ‘quick & easy’ solution i could find.
Click to expand
Note: variable sample rates might be on by default now making this step obsolete
In pipewire.conf
set:
default.clock.allowed-rates = [ 44100 48000 ]
in pipewire-pulse.conf
set:
pulse.min.req = 1024/48000 # 21ms, see: https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-PulseAudio
For applications that the above two settings do not solve, use environment variables:
PULSE_LATENCY_MSEC=[INT] # Example: PULSE_LATENCY_MSEC=128
PIPEWIRE_LATENCY=[QUANT]/[RATE] # Example: PIPEWIRE_LATENCY=2048/48000
To manually set the buffer size on a per application basis.
Note: PIPEWIRE_LATENCY
does not work for pipewire-pulse, use PULSE_LATENCY_MSEC
instead.
Note: PULSE_LATENCY_MSEC
currently does not work as cleanly as it does in pulseaudio, when using this setting, confirm that the correct latency is being set with pw-top
.
Full Guide:
-
Create the config files for pipewire and wireplumber (If they don’t exist)
You only need one set of config files. User config files will override system config files for your user account if the user config files exist.
Create System Config Files:
sudo mkdir -p /etc/pipewire/ && sudo mkdir -p /etc/wireplumber/wireplumber.conf.d/ && sudo cp /usr/share/pipewire/*.conf /etc/pipewire/ && sudo cp /usr/share/wireplumber/wireplumber.conf.d/* /etc/wireplumber/wireplumber.conf.d/
Or create User Config Files:
mkdir -p ~/.config/pipewire/ && mkdir -p ~/.config/wireplumber/wireplumber.conf.d/ && cp /usr/share/pipewire/*.conf ~/.config/pipewire/ && cp /usr/share/wireplumber/wireplumber.conf.d/* ~/.config/wireplumber/wireplumber.conf.d/
Note:
alsa-vm.conf
which we will edit later in the guide should be placed in.../wireplumber/wireplumber.conf.d
directory that we just created. -
Disable Suspend
Some soundcards become problematic when suspend is enabled, disabling it could fix all problems for some users.
- In
alsa-vm.conf
addsession.suspend-timeout-seconds = 0
like so:
actions = { update-props = { session.suspend-timeout-seconds = 0
- Restart pipewire to apply
- In
-
Enable sample rate switching
Note: This setting might actually be set by default now making this step obsolete.
Some applications need to be able to run at 44.1khz or they will have crackling (common issue for instance for games run through Wine). This is easy to fix.- In
pipewire.conf
change
to:#default.clock.allowed-rates = [ 48000 ]
default.clock.allowed-rates = [ 44100 48000 ] # This is not default because: https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-PipeWire#setting-global-sample-rate
- Restart pipewire to apply.
- Now these applications should be allowed to run at 44.1khz instead of the default 48khz clock rate thus reducing likelihood of issues such as crackling.
- In
-
Try tweaking alsa headroom
If enabling sample rate switching was not enough to solve the issue, try changing the alsa headroom setting next to see if that solves the issue.- In
alsa-vm.conf
changeapi.alsa.headroom = 1024 # See: https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/alsa.html ```
to
api.alsa.headroom = 0
- Restart pipewire to apply.
- If setting headroom to 0 makes it worse, try setting it to 2048
- Other settings to try: 512, 256, 128, 64, 32
- It is recommended to use the lowest value that works well.
- In
-
Try tweaking the alsa period size
If the problem still isn’t resolved, try changing the alsa period size.- In
alsa-vm.conf
change
toapi.alsa.period-size = 1024
# See: https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/alsa.html api.alsa.period-size = 256
- Restart pipewire to apply.
- If this does not solve your issue, try setting it to different values (512, 128, 64 and maybe 2048).
- If it still doesn’t solve your issues, try different combinations of period-size and headroom configurations until you find a good combination or give up.
- In
-
Set the playback buffer size
If none of the above solved the issue, you should try setting the audio buffer size/latency.When an application has it’s own audio buffer size setting you will want to use that to do this, for example:
chromium --audio-buffer-size=2048 # Sets latency to about 40ms"
For applications that do not support configuring their audio buffer size, we can use system variables.
Try setting the latency to about 20ms by running:
PULSE_LATENCY_MSEC=83 COMMAND # Works for pipewire-pulse (most applications use this!) #or PIPEWIRE_LATENCY=1024/48000 COMMAND # Works for pipewire, pipewire-alsa & pipewire-jack.
Where
COMMAND
is the executable for the program you’re having problems with.Confirm with
pw-top
that the latency is correct (QUANT should be between 1024 and 1050)
If that was not enough, try setting the latency to about 40ms by running:
PULSE_LATENCY_MSEC=126 COMMAND # Works for pipewire-pulse (most applications use this!) #or PIPEWIRE_LATENCY=2048/48000 COMMAND # Works for pipewire, pipewire-alsa & pipewire-jack.
Where
COMMAND
is the executable for the program you’re having problems with.Confirm with
pw-top
that the latency is correct (QUANT should be between 2048 and 2100)
The vast majority of applications use pulseaudio, and therefore pipewire-pulse, which means that you will almost always use the
PULSE_LATENCY_MSEC
variable rather thanPIPEWIRE_LATENCY
.When in doubt, always use
pw-top
to check the quant values of running audio streams to make sure that the command worked.
Why am I saying it’s 20ms when
PULSE_LATENCY_MSEC
is to set it to 86? or that it’s 40ms when set to 128?Click to expand
The reason is that if I look at the application in
pw-top
and see theQUANT
andRATE
values and do the math for total latency as mentioned in the tips above, that’s the actual latency the application seems to be getting set to. Remember, this is pipewire, not pulse. It seems that this variable simply behaves differently here, but if I am actually wrong about this, I invite anyone who knows better to inform me about it in the comments below.
If this solves your issue, then I suggest you just stick to setting the
PULSE_LATENCY_MSEC
variable as needed for individual applications, and just edit the.desktop
file shortcuts used by your DE/Launcher, or create aliases in.bashrc
for all offending applications. -
Set minimum playback buffer size
If you would rather have the audio buffer size set systemwide instead of applying it on a per-application basis, inpipewire-pulse.conf
change:#pulse.min.req = 256/48000 # 5ms
to
pulse.min.req = 1024/48000 # 21ms, see: https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-PulseAudio#playback-buffering-options
Restart pipewire to apply.
I would advise against setting this any higher as it can cause some issues, if there are applications that need 40ms latency, you really should just set those manually instead.
The above only requests 21ms latency though, applications can still force a lower latency so this is a sort of soft setting for the minimum buffer size. Even then, on my system this setting helped a lot.
To truly force it (I would advise against this as it can cause issues in some applications), in
pipewire-pulse.conf
:#pulse.min.quantum = 256/48000 # 5ms
to
pulse.min.quantum = 1024/48000 # 21ms, see: https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-PulseAudio#scheduling-options
Restart pipewire to apply.
I very strongly(!!) advise against this, but if you want to set systemwide latency for everything (not just pipewire-pulse), change in
pipewire.conf
:#default.clock.min-quantum = 32
to
default.clock.min-quantum = 1024 # You preferably should not use this setting! See: https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-PipeWire#setting-buffer-size
Never(!!) set this higher than 1024, stuff will start breaking, even when set to 1024 some applications can break, but it’s not very common unless you go higher.)
Restart pipewire to apply.
I highly suggest though that instead of doing this, you would rather use the
PIPEWIRE_LATENCY
variable on a per-application basis instead of facing the risks of using this setting.
If you have any additional tips for this tutorial, please leave them below.