Fixing an issue with PipeWire and Spotify
2022-04-21 updated 2023-01-20
2023 update: This seems to be working fine with newer versions of PipeWire.
I'd notice that Spotify was dropping out and stuttering when I received notifications from Slack. I suspected an issue with sample rates or buffer size.
A search for pipewire in NixOS options led to pipewire.conf.in, which includes the defaults.
I found PulseAudio & PipeWire documentation, by searching for "pulse.min.quantum", which introduced the meaning of the settings.
I also searched for "spotify stutter pipewire", which turned up some issues, which suggested configuring some PipeWire options (rather than PipeWire-PulseAudio options). This also suggested using pw-top for debugging the issue.
I saw the following output:
S ID QUANT RATE WAIT BUSY W/Q B/Q ERR NAME
55 1024 48000 250.6µs 34.6µs 0.01 0.00 0 alsa_output.usb-Schiit_Audio_I_m_Fulla_Schiit-00.analog-stereo
89 8192 44100 96.7µs 698.2µs 0.00 0.03 0 + spotify
84 1024 48000 99.0µs 55.8µs 0.00 0.00 0 + ChromiumFrom this, I noticed that the quantum value ("QUANT") and the sample rate ("RATE") were mismatched between spotify and Chromium (since, of course, Slack is a web app).
Suspecting a sample rate mismatch, I read through the PipeWire options and found a way to set the sample rate from the command-line, as well as a way to read the current settings, which let me see what my random experiments with writing configuration files was actually doing.
$ pw-metadata -n settings
Found "settings" metadata 30
update: id:0 key:'log.level' value:'2' type:''
update: id:0 key:'clock.rate' value:'48000' type:''
update: id:0 key:'clock.allowed-rates' value:'[ 48000 ]' type:''
update: id:0 key:'clock.quantum' value:'1024' type:''
update: id:0 key:'clock.min-quantum' value:'32' type:''
update: id:0 key:'clock.max-quantum' value:'8096' type:''
update: id:0 key:'clock.force-quantum' value:'0' type:''
update: id:0 key:'clock.force-rate' value:'0' type:''I set the clock rate and observed that it changed in the settings and pw-top, but this didn't fix the issue.
pw-metadata -n settings 0 clock.allowed-rates '[ 44100 ]'
pw-metadata -n settings 0 clock.rate 44100I then stared at pw-top for a while to see if I could identify the point at which audio dropouts occurred, and noticed that it happened when the "QUANT" value for the output device jumped from 512 to 8192:
S ID QUANT RATE WAIT BUSY W/Q B/Q ERR NAME
55 512 44100 269.7µs 57.5µs 0.02 0.00 0 alsa_output.usb-Schiit_Audio_I_m_Fulla_Schiit-00.analog-stereo
89 8192 44100 99.1µs 43.3µs 0.01 0.00 0 + spotify
87 1024 48000 135.2µs 61.3µs 0.01 0.01 0 + ChromiumAnd after Chromium stopped:
55 8192 44100 205.4µs 34.5µs 0.01 0.00 0 alsa_output.usb-Schiit_Audio_I_m_Fulla_Schiit-00.analog-stereo
89 8192 44100 54.8µs 61.9µs 0.00 0.00 0 + spotifySo I adjusted the value of clock.max-quantum using pw-metadata:
pw-metadata -n settings 0 clock.max-quantum 1024I noted that the quantum value in pw-top changed immediately, and I could no longer hear audio dropouts when the Chromium process exited. I could also manually trigger the stutter by setting the value between 512 and 8192!
So I patched this in my NixOS configuration with the following:
services.pipewire = {
enable = true;
alsa.enable = true;
pulse.enable = true;
config.pipewire = {
"context.properties" = {
"default.clock.max-quantum" = 1024; # avoid stutter when Spotify raises quantum suddenly
};
};
};I might also decide to leave the sample rate fixed to 44.1k in the future, but it's not like I can hear resampling noise.
Appendix 1: Summary of failed attempts
- Disabling PipeWire's PulseAudio and ALSA support just broke audio. (I was hoping that I had some unnecessary feature enabled).
- I compared it against other versions of Spotify, which led me nowhere (<open.spotify.com>: OK; new native client: still had issues).
- I suspected a media-session issue, since upstream now recommends
wireplumberfor media-session management. However, that's only recently been merged into the next NixOS version. - I tried changing the configuration values manually by patching my NixOS configuration, or adding files to
~/.config/pipewireand reloading the PipeWire services. I couldn't verify that this would actually do anything, until I learned aboutpw-metadata, after which I just used that instead.
Appendix 2: Retrospective
If I'd done only the following, I wouldn't have needed to do anything else (the "critical path"):
- identify that
pw-topprovides enough observability into the live state of PipeWire - stare at
pw-topand identify that a large jump in the quantum value happens at the same time as audio dropouts. - manually set the max-quantum value to identify a value that doesn't cause audio dropouts.
As it was, this took me 1 hour to diagnose and fix, and I spent 45 minutes writing up this document.