Pipewire xruns with Firefox

Hello all,
I have been fighting with pipewire and audio issues with firefox that are xruns (crackling audio) during playback.
Hardware: iFi Zen Dac V1,
Kernel: 6.15.2-2 (this has been happening since last year so I don’t think this is it)
DE: KDE Plasma

I have followed the steps here:

And spent the better part of the day fighting with this.

Additionally I have h/w acceleration disabled in FF. At the end of all of this its a little better (placebo effect?) but still driving me absolutely mad.

Any suggestions, links, comments, etc are highly appreciated!

I am not sure if xruns is the right word here, its like a static or crackle almost and it seems to be randomly happening with audio in firefox.
I dont see anything inherantly wrong here, but I am a novice with pipewire and more adept to setting up alsa.

Let me get some more concise info here and what I have tried to resolve this - as a preface none of this has resolved the issue, maybe made it better, possibly…

Issue: Crackling in audio randomly, easily reproduced by skipping the play head around in a song specifically with Firefox (but this may not be limited entirely to FF).

Tried so far:
Firefox - disable hardware acceleration

Copied pipewire config files to ~/.config/(pipewire / wireplumber)

Modified
pipewire.conf

default.clock.allowed-rates = [ 44100 48000 ]  
default.clock.min-quantum   = 1024

alsa-vm.conf
api.alsa.headroom = 0

  • restart pipewire and test (no change)
  • re-modify with 32 and doubling (64, 128…) back to 2048, with a restart of pipewire and test for each new setting

pipewire-pulse.conf

pulse.min.req = 1024/48000
pulse.min.quantum      = 1024/48000

alsa-vm.conf
api.alsa.period-size = 256

  • as before re-modify 0, 32, 64… to 2048 restarting pipewire and testing each time

Re-test the 2 above with different combinations - restarting pipewire and testing each time

launching firefox with
--audio-buffer-size=2048

running firefox with
PIPEWIRE_LATENCY=1024/48000 firefox

edit and save
/etc/wireplumber/main.lua.d/50-alsa-config.lua

alsa_monitor.rules = {
  
  -- (...abbreviated for legibility...)
  
  {
    apply_properties = {
      -- (...abbreviated for legibility...)
      ["session.suspend-timeout-seconds"] = 0, -- default is 5
    },
  },
}
sed -i "s/reader.parse-on-load.enabled\", true/reader.parse-on-load.enabled\", false/" $(find ~/.mozilla/firefox/ -name prefs.js)
sed -i "s/media.webspeech.synth.enabled\", true/media.webspeech.synth.enabled\", false/" $(find ~/.mozilla/firefox/ -name prefs.js)

Bumping this again, another 2 days of playing with configs and zero resolution.

I am reporting back with some progress, hopefully this helps someone else going through this.

I believe this is all caused by the inability to lock the sample rate and bit depth with Pipewire. There is a “default” setting for this, but that seems to be more of a suggestion than anything as many applications ignore this entirely.

That was not the case with Alsa for example you could lock those and they were static. Some folks would argue that if your audio source was inferior to sample rate and bit depth it would just be 0’s for the missing data and it doesn’t make a difference.
This is where I disagree, locking the sample rate and bit depth would avoid a situation like this entirely (it did with Alsa). Do a quick web search for “pipewire cracking” and you will see I am far from the only person with this issue.

I am going to approach this like I found this thread first, and have not done anything at this point to resolve this.

As a warning: I am not 100% sure what all of Step 8 does, a lot of this is self explanatory, but that one loses me a bit. I attempted it out of desperation and by some miracle it worked.

If you are more knowledgeable, or have a better way of accomplishing this please share it with everyone.

Resolution:

  • Step 1: Copy config files to your ~/.config this is important for one main reason, if you mess something up you can nuke the /.config/pipewire and ./config/wireplumber folders.
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/
  • Step 2: Edit ~/.config/pipewire/pipewire-pulse.conf - Modify the following line. This removed the pops when scrubbing or starting playback.
                pulse.idle.timeout     = 0              # pause after 5 seconds of underrun
  • Step 3: Research your hardware and find the sample rates and bit depth it supports. Yours may differ from another thread your looking at.

  • Step 4: Edit ~/.config/pipewire/pipewire.conf - Your choice of editor (I am old school and like nano). Replace this section here with whatever your hardware supports. I picked the highest sample rate and bit depth supported to easily spot anything misbehaving.
    (this is relevant for the iFi Zen Dac V1/2/3)

 default.clock.rate          = 384000
    default.clock.allowed-rates = [ 48000 96000 88200 176400 192000 352800 384000 ]
    default.clock.quantum       = 1024
    default.clock.min-quantum   = s32le
  • Step 5: Edit ~/.config/wireplumber/wireplumber.conf.d/alsa-vm.conf - I had the best luck with the settings below, your mileage may vary. From what I have read keeping these under 2048 is advisable, but I have cranked them to 8000 without any difference from 2048.
api.alsa.period-size   = 2048
        api.alsa.headroom      = 2048
  • Step 6: This may be optional but it is part of making this mess work for me.
mkdir ~/.config/wireplumber/main.lua.d/

In that directory make a file called “50-alsa-config.lua” with the following (Match the rates to your hardware here)

--["audio.channels"]         = 2,
--["audio.format"]           = "S32LE",
--["audio.rate"]             = 384000,
--["audio.allowed-rates"]   = "44100 48000 96000 88200 176400 192000 352800 384000",
--["audio.position"]         = "FL,FR",
--["api.alsa.period-size"]   = 1024,

I am not 100% this is entirely necessary, however it is part of whatever voodoo made this work for me.

  • Step 7: This change was made system wide, and I believe it is actually why Pipewire kind of listens to the “defaults” in step 3.
sudo nano /usr/lib/systemd/system/rtkit-daemon.service.d

In that directory edit or create “limits.conf” with the following.

[Service]
EnvironmentFile=/etc/sysconfig/rtkit
ExecStart=
ExecStart=/usr/libexec/rtkit-daemon $RTKIT_ARGS
  • Step 8:
sudo mkdir /etc/sysconfig

In that directory edit or create a file called “rkit” with the following.

RTKIT_ARGS="--scheduling-policy=FIFO
--our-realtime-priority=89
--max-realtime-priority=88
--min-nice-level=-19
--rttime-usec-max=2000000
--users-max=100
--processes-per-user-max=1000
--threads-per-user-max=10000
--actions-burst-sec=10
--actions-per-burst-max=1000
--canary-cheep-msec=30000
--canary-watchdog-msec=60000
"
  • Step 9: Restart audio services.
systemctl --user restart pipewire pipewire-pulse wireplumber

Welp…
Still happening, really not liking Pipewire.

This ONLY happens with firefox at 44100

Still fighting with this. The other day I almost broke down and bought another AMP/DAC, thing is nothing is wrong with my current one and I really love how it sounds.

Open to suggestions if anyone has any to offer…

Sorry to bump an old thread. But I am also fighting random crackling issues, not in Firefox but in games. If pw-top report no ERR, as ERR is 0 in your case, it’s most likely hardware interference and not a software configuration or error. USB3 is sometimes notorious for producing interference and switching to USB2 might help.

Having the same issue (detailed in another post).

It seems purely a software issue (unknown wehther due to Xruns) because this happens only in Cachy—not Mint nor Winblows^11.

I’ve tried every USB 3.2 and USB 2 port.

I have yet to try a USB 2 to USB-C (USB 4) adapter.

No matter which kernel, WirePlumber, or PipeWire setting I change, including rt/realtime setting, crackling behavior seems about the same.

Thus far, the only way I’ve been able to cause noticeable effect is setting the quantum too low, which produces a slowed robotic stutter.