PipeWire: Difference between revisions
imported>Hypnosis2839 m →Enabling PipeWire: fix formatting |
imported>Hcsch No edit summary |
||
Line 29: | Line 29: | ||
PipeWire can be configured to use specific codecs. The mSBC codec provides slightly better sound quality in calls than regular HFP/HSP, while the SBC-XQ provides better sound quality for audio listening. For more information [https://www.guyrutenberg.com/2021/03/11/replacing-pulseaudio-with-pipewire/ see this link]. | PipeWire can be configured to use specific codecs. The mSBC codec provides slightly better sound quality in calls than regular HFP/HSP, while the SBC-XQ provides better sound quality for audio listening. For more information [https://www.guyrutenberg.com/2021/03/11/replacing-pulseaudio-with-pipewire/ see this link]. | ||
Wireplumber (<code>services.pipewire.wireplumber</code>) is the default modular session / policy manager for PipeWire in unstable, however there is currently no way to configure the advanced settings using the module. However, you can | Wireplumber (<code>services.pipewire.wireplumber</code>) is the default modular session / policy manager for PipeWire in unstable, however there is currently no way to configure the advanced settings using the module. However, with 24.05 you can use <code>services.pipewire.wireplumber.configPackages</code> to create drop-in Lua files directly in the expected path (<code>/etc/wireplumber/bluetooth.lua.d</code>). For example: | ||
<syntaxHighlight lang=nix> | |||
services.pipewire.wireplumber.configPackages = [ | |||
(pkgs.writeTextDir "share/wireplumber/bluetooth.lua.d/51-bluez-config.lua" '' | |||
bluez_monitor.properties = { | |||
["bluez5.enable-sbc-xq"] = true, | |||
["bluez5.enable-msbc"] = true, | |||
["bluez5.enable-hw-volume"] = true, | |||
["bluez5.headset-roles"] = "[ hsp_hs hsp_ag hfp_hf hfp_ag ]" | |||
} | |||
'') | |||
]; | |||
</syntaxHighlight> | |||
Once [https://github.com/NixOS/nixpkgs/pull/292115 #292115] is merged and has reached nixos-unstable, you'll be able to use <code>services.pipewire.wireplumber.extraLuaConfig</code> as well: | |||
<syntaxHighlight lang=nix> | |||
services.pipewire.wireplumber.extraLuaConfig.bluetooth."51-bluez-config" = '' | |||
bluez_monitor.properties = { | |||
["bluez5.enable-sbc-xq"] = true, | |||
["bluez5.enable-msbc"] = true, | |||
["bluez5.enable-hw-volume"] = true, | |||
["bluez5.headset-roles"] = "[ hsp_hs hsp_ag hfp_hf hfp_ag ]" | |||
} | |||
''; | |||
</syntaxHighlight> | |||
If you are still using 23.11 or earlier, you can specify these files in <code>environment.etc</code>: | |||
<syntaxHighlight lang=nix> | <syntaxHighlight lang=nix> | ||
Line 94: | Line 122: | ||
<strong>Note</strong>: those cards can be set to the "Pro Audio" profile with <code>pavucontrol</code> so PipeWire doesn't try to guess a wrong channel layout for them. | <strong>Note</strong>: those cards can be set to the "Pro Audio" profile with <code>pavucontrol</code> so PipeWire doesn't try to guess a wrong channel layout for them. | ||
For NixOS 24.05 and newer: | |||
<syntaxHighlight lang=nix> | |||
services.pipewire.extraConfig.pipewire."91-null-sinks" = { | |||
context.objects = [ | |||
{ | |||
# A default dummy driver. This handles nodes marked with the "node.always-driver" | |||
# properyty when no other driver is currently active. JACK clients need this. | |||
factory = "spa-node-factory"; | |||
args = { | |||
factory.name = "support.node.driver"; | |||
node.name = "Dummy-Driver"; | |||
priority.driver = 8000; | |||
}; | |||
} | |||
{ | |||
factory = "adapter"; | |||
args = { | |||
factory.name = "support.null-audio-sink"; | |||
node.name = "Microphone-Proxy"; | |||
node.description = "Microphone"; | |||
media.class = "Audio/Source/Virtual"; | |||
audio.position = "MONO"; | |||
}; | |||
} | |||
{ | |||
factory = "adapter"; | |||
args = { | |||
factory.name = "support.null-audio-sink"; | |||
node.name = "Main-Output-Proxy"; | |||
node.description = "Main Output"; | |||
media.class = "Audio/Sink"; | |||
audio.position = "FL,FR"; | |||
}; | |||
} | |||
]; | |||
}; | |||
</syntaxHighlight> | |||
If you're still using 23.11 or earlier, you can use <code>environment.etc</code> and <code>pkgs.formats.json</code>: | |||
<syntaxHighlight lang=nix> | <syntaxHighlight lang=nix> | ||
environment.etc = let | environment.etc = let | ||
Line 153: | Line 220: | ||
Audio production and rhythm games require lower latency audio than general applications. PipeWire can achieve the required latency with much less CPU usage compared to PulseAudio, with the appropriate configuration. | Audio production and rhythm games require lower latency audio than general applications. PipeWire can achieve the required latency with much less CPU usage compared to PulseAudio, with the appropriate configuration. | ||
The minimum period size controls how small a buffer can be. The lower it is, the less latency there is. PipeWire has a value of 32/48000 by default, which amounts to 0.667ms. It can be brought lower if needed: | The minimum period size controls how small a buffer can be. The lower it is, the less latency there is. PipeWire has a value of 32/48000 by default, which amounts to 0.667ms. It can be brought lower if needed: | ||
For 24.05 and newer: | |||
<syntaxHighlight lang=nix> | <syntaxHighlight lang=nix> | ||
services.pipewire.extraConfig.pipewire."92-low-latency" = { | |||
context.properties = { | |||
default.clock.rate = 48000 | |||
default.clock.quantum = 32 | |||
default.clock.min-quantum = 32 | |||
default.clock.max-quantum = 32 | |||
} | |||
}; | }; | ||
</syntaxHighlight> | </syntaxHighlight> | ||
If you're still using 23.11 or earlier, you can use <code>environment.etc</code> and <code>pkgs.formats.json</code> like in [[PipeWire|Advanced Configuration]]. | |||
<strong>NOTE</strong>: Every setup is different, and a lot of factors determine your final latency, like CPU speed, RT/PREEMPTIVE kernels and soundcards supporting different audio formats. That's why 32/48000 isn't always a value that's going to work for everyone. The best way to get everything working is to keep increasing the quant value until you get no crackles (underruns) or until you get audio again (in case there wasn't any). This won't guarantee the lowest possible latency, but will provide a decent one paired with stable audio. | <strong>NOTE</strong>: Every setup is different, and a lot of factors determine your final latency, like CPU speed, RT/PREEMPTIVE kernels and soundcards supporting different audio formats. That's why 32/48000 isn't always a value that's going to work for everyone. The best way to get everything working is to keep increasing the quant value until you get no crackles (underruns) or until you get audio again (in case there wasn't any). This won't guarantee the lowest possible latency, but will provide a decent one paired with stable audio. | ||
Line 170: | Line 238: | ||
===PulseAudio backend=== | ===PulseAudio backend=== | ||
Applications using the Pulse backend have a separate configuration. The default minimum value is 1024, so it needs to be tweaked if low-latency audio is desired. | Applications using the Pulse backend have a separate configuration. The default minimum value is 1024, so it needs to be tweaked if low-latency audio is desired. | ||
For 24.05 or newer: | |||
<syntaxHighlight lang=nix> | <syntaxHighlight lang=nix> | ||
services.pipewire.extraConfig.pipewire-pulse."92-low-latency" = { | |||
context.modules = [ | |||
{ | |||
name = "libpipewire-module-protocol-pulse"; | |||
args = { | |||
pulse.min.req = "32/48000"; | |||
pulse.default.req = "32/48000"; | |||
pulse.max.req = "32/48000"; | |||
pulse.min.quantum = "32/48000"; | |||
pulse.max.quantum = "32/48000"; | |||
}; | |||
} | |||
]; | |||
stream.properties = { | |||
node.latency = "32/48000"; | |||
resample.quality = 1; | |||
}; | }; | ||
}; | }; | ||
</syntaxHighlight> | </syntaxHighlight> | ||
If you're still using 23.11 or earlier, you can use <code>environment.etc</code> and <code>pkgs.formats.json</code> like in [[PipeWire|Advanced Configuration]]. | |||
As a general rule, the values in <code>pipewire-pulse</code> should not be lower than the ones in <code>pipewire</code>. | As a general rule, the values in <code>pipewire-pulse</code> should not be lower than the ones in <code>pipewire</code>. | ||
===Controlling the ALSA devices=== | ===Controlling the ALSA devices=== | ||
It is possible to configure various aspects of soundcards through PipeWire, including format, period size and batch mode: | It is possible to configure various aspects of soundcards through PipeWire, including format, period size and batch mode: | ||
For 24.05 and newer: | |||
<syntaxHighlight lang=nix> | |||
services.pipewire.wireplumber.configPackages = [ | |||
(pkgs.writeTextDir "share/wireplumber/main.lua.d/99-alsa-lowlatency.lua" '' | |||
alsa_monitor.rules = { | |||
{ | |||
matches = {{{ "node.name", "matches", "alsa_output.*" }}}; | |||
apply_properties = { | |||
["audio.format"] = "S32LE", | |||
["audio.rate"] = "96000", -- for USB soundcards it should be twice your desired rate | |||
["api.alsa.period-size"] = 2, -- defaults to 1024, tweak by trial-and-error | |||
-- ["api.alsa.disable-batch"] = true, -- generally, USB soundcards use the batch mode | |||
}, | |||
}, | |||
} | |||
'') | |||
];; | |||
</syntaxHighlight> | |||
Once [https://github.com/NixOS/nixpkgs/pull/292115 #292115] is merged and has reached nixos-unstable, you'll be able to use <code>services.pipewire.wireplumber.extraLuaConfig</code> as well: | |||
<syntaxHighlight lang=nix> | |||
services.pipewire.wireplumber.extraLuaConfig.main."99-alsa-lowlatency" = '' | |||
alsa_monitor.rules = { | |||
{ | |||
matches = {{{ "node.name", "matches", "alsa_output.*" }}}; | |||
apply_properties = { | |||
["audio.format"] = "S32LE", | |||
["audio.rate"] = "96000", -- for USB soundcards it should be twice your desired rate | |||
["api.alsa.period-size"] = 2, -- defaults to 1024, tweak by trial-and-error | |||
-- ["api.alsa.disable-batch"] = true, -- generally, USB soundcards use the batch mode | |||
}, | |||
}, | |||
} | |||
''; | |||
</syntaxHighlight> | |||
If you're still using 23.11 or earlier, you can use <code>environment.etc</code>: | |||
<syntaxHighlight lang=nix> | <syntaxHighlight lang=nix> | ||
environment.etc. | environment.etc. | ||
Line 212: | Line 317: | ||
} | } | ||
'';</syntaxHighlight> | '';</syntaxHighlight> | ||
The <code>matches</code> attribute applies the <code>actions</code> to the devices/properties listed there. It is usually used with soundcard names, like shown in the config above. <code><matches></code> can match any of the outputs of | The <code>matches</code> attribute applies the <code>actions</code> to the devices/properties listed there. It is usually used with soundcard names, like shown in the config above. <code><matches></code> can match any of the outputs of | ||
<syntaxHighlight lang=console> | <syntaxHighlight lang=console> |