Pipewire
Overview
A low-level multimedia framework.
Restart pipewire components with:
systemctl --user restart wireplumber pipewire pipewire-pulse
Sample rate
Allowing both 44.1kHz and 48kHz may help fixing some cracklings.
cp /usr/share/pipewire/pipewire.conf ~/.config/pipewire/pipewire.conf
Add to ~/.config/pipewire/pipewire.conf
> context.modules
:
default.clock.allowed-rates = [ 44100 48000 ]
Nice level
For the time I'm writing this (2022/11/27), the default client-rt.conf
does not contain a default nice.level
, which makes applications that use pipewire directly (not through pipewire-pulse) have a lower priority. mpv
, for example, was having some audio cracklings.
cp /usr/share/pipewire/client-rt.conf ~/.config/pipewire/client-rt.conf
Add to ~/.config/pipewire/client-rt.conf
> context.modules
> libpipewire-module-rt
:
args = {
nice.level = -11
}
Sink/source management
List
List sources/sinks:
pactl list short sources
pactl list short sinks
wpctl status
Default Sink
Copy the base pipewire-pulse configuration:
cp /usr/share/pipewire/pipewire-pulse.conf ~/.config/pipewire/pipewire-pulse.conf
Then append the following to context.exec
:
context.exec = [
{ path = "/usr/bin/sh" args = "/path/to/pipewire-init.sh" }
]
Create the pipewire-init.sh
with the command that sets the default sink (and optionally add more initialization commands).
##!/usr/bin/sh
sleep 0.5
pactl set-default-sink alsa_output.pci-0000_2f_00.4.analog-stereo
Using pipewire (untested)
Add the following to pipewire.conf
:
context.properties = {
default.configured.audio.sink = { "name": "your_device_name" }
}
Virtual Sink
Create a sink that can be selected in applications and that forwards the data to another sink. Useful, for example, if you want to record audio from only one application.
To create the sink temporarily, run either:
pactl load-module module-remap-sink sink_name=recording
pw-loopback --name='Recording' --capture-props='media.class=Audio/Sink node.name=recording'
To create the sink permanently, create ~/.config/pipewire/pipewire-pulse.conf.d/10-remap-sink.conf
and restart pipewire.
context.modules = [
{ name = libpipewire-module-loopback
args = {
node.description = "Audio/Sink Recording"
capture.props = {
media.class = "Audio/Sink"
node.name = recording
audio.position = [FL FR]
}
playback.props = {
audio.position = [FL FR]
}
}
}
]
Combine sources
1) Create a null sink
To create the sink temporarily:
pactl load-module module-null-sink sink_name=mix
pw-cli create-node adapter factory.name=support.null-audio-sink media.class="Audio/Sink" object.linger=1 monitor.channel-volumes=1 node.name=mix
To create the sink permanently, create ~/.config/pipewire/pipewire.conf.d/10-null-sink.conf
and restart pipewire.
context.objects = [
{ factory = adapter
args = {
factory.name = support.null-audio-sink
media.class = "Audio/Sink"
node.name = mix
node.description = "NullSink Mix"
object.linger = 1
monitor.channel-volumes = 1
}
}
]
2) Connect sources to the null sink
pactl load-module module-loopback sink=mix source=${speakers}
pactl load-module module-loopback sink=mix channels=2 channel_map=mono,mono source=${mic}
pw-loopback --capture=${speakers} --capture-props='stream.capture.sink=true' --playback=mix
pw-loopback --capture=${mic} --capture-props='audio.position=[FL] stream.dont-remix=true' --playback=mix --playback-props='audio.position=[MONO]'
The mix
sink with have the audio of both sources.
Note: PIPEWIRE_NODE
environment variable seems to affect the module-loopback
in a way that makes it not work.