Sound
For audio handling on Linux, PipeWire is the currently recommended framework.
PipeWire is a server and user space API that provides a platform to handle multimedia pipelines. It is a modern, low-latency audio and video server designed to work with the latest audio use cases and handle professional audio interfaces and applications.
PipeWire was created as a replacement for both the PulseAudio sound server and the Jack Audio Connection Kit (JACK) server. It provides a unified interface for handling video and audio streams and is intended to be flexible and extensible, allowing it to address not only audio but other multimedia tasks as well, such as video conferencing, screen capture, and other multimedia applications. It can also work with different hardware devices, including webcams, microphones, and professional audio devices.
Additionally, it integrates better with the security models of Flatpak and Wayland. It does so via sandboxing processes from one another, preventing an application from snooping on other applications' audio streams. Before allowing an application to record audio or sharing the screen(e.g. in a browser over WebRTC) it will ask the user for permission to do so.
PipeWire implements no connection logic internally, that is the responsibility of a program called a session manager. It watches for new streams and connects them to the appropriate output device or application.
There are two session managers to choose from:
- PipeWire Media Session: A very simple session manager that caters to some basic desktop use cases. It was mostly implemented for testing and as an example for building new session managers.
- WirePlumber: A more powerful manager and the current recommendation. It is based on a modular design, with Lua plugins that implement the actual management functionality.
WirePlumber is the recommended choice, as it is better maintained, receives regular updates and is more feature-rich.
Installation
The most basic PipeWire setup includes the following packages:
NOTE: PipeWire handles Bluetooth audio devices if the pipewire-audio
package is installed.
pacman -S pipewire pipewire-audio wireplumber
Additional packages can be installed to extend PipeWire's compatibility and capabilities:
Package | Description |
---|---|
pipewire-alsa |
Support for routing ALSA clients through PipwWire |
pipewire-jack |
Support for JACK clients |
pipewire-pulse |
Support for PulseAudio clients (recommended) |
pipewire-v4l2 |
Support for handling video devices, e.g. webcams, tuners, etc. |
pipewire-zeroconf |
Support for streaming audio over the network, e.g. an AirPlay receiver |
Streaming audio to an AirPlay receiver
PipeWire can send audio to an AirPlay receiver via the pipewire-zeroconf
package, which includes the necessary RTSP/RAOP modules to create a sink to send audio data to. This requires the Avahi zeroconf daemon.
Install the Avahi package along with nss-mdns
:
Install Avahi
pacman -S avahi nss-mdns
Setting up mDNS
WARNING: If you use systemd-resolved
, make sure to disable its built-in mDNS resolver/responder, as it will conflict with Avahi's mDNS resolver.
Edit /etc/nsswitch.conf
and change the line starting with hosts
to include mdns_minimal [NOTFOUND=return]
before resolve
and dns
:
hosts: mymachines mdns_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] files myhostname dns
If you're using a firewall, make sure that the following ports are open:
TIP: firewalld
has a preset for RTSP. Make sure to apply the firewall changes permanently.
Port | Protocol | Service |
---|---|---|
554 | TCP | RTSP |
554 | UDP | RTSP |
6001 | UDP | Some 3rd party AirPlay receivers use this |
6002 | UDP | Some 3rd party AirPlay receivers use this |
Auto-load PipeWire RAOP discovery module
Create a new drop-in config file, e.g. ~/.config/pipewire/pipewire.conf.d/raop-discover.conf
:
context.modules = [
{
name = libpipewire-module-raop-discover
args = {
#raop.latency.ms = 1000
stream.rules = [
{
matches = [
{
raop.ip = "~.*"
#raop.ip.version = 4 | 6
#raop.ip.version = 4
#raop.port = 1000
#raop.name = ""
#raop.hostname = ""
#raop.domain = ""
#raop.device = ""
#raop.transport = "udp" | "tcp"
#raop.encryption.type = "RSA" | "auth_setup" | "none"
#raop.audio.codec = "PCM" | "ALAC" | "AAC" | "AAC-ELD"
#audio.channels = 2
#audio.format = "S16" | "S24" | "S32"
#audio.rate = 44100
#device.model = ""
}
]
actions = {
create-stream = {
#raop.password = ""
stream.props = {
#target.object = ""
#media.class = "Audio/Sink"
}
}
}
}
]
}
}
]
Restart the pipewire
user unit to make pipewire read in the new drop-in config file and load the RAOP module automatically upon login:
Re/start services
systemctl restart --user pipewire
Enable and start avahi-daemon.service
:
systemctl enable --now avahi-daemon.service
Scan for devices on the network
You can use the avahi-browse
utility to scan for devices on your network:
avahi-browse --all --ignore-local --terminate
This will produce a list of devices broadcasting mDNS services over the network (not only AirPlay, but also file sharing, Spotify, Home Kit and various others).
You should now be able to ping
your AirPlay receiver using its .local
DNS name:
ping my-airplay-receiver.local
If everything worked as intended wpctl status
should list new sinks to output audio to:
...
Audio
├─ Devices:
│ 53. Starship/Matisse HD Audio Controller [alsa]
│
├─ Sinks:
│ 47. My AirPlay Reciever [vol: 1.00]
│ * 61. Starship/Matisse HD Audio Controller Analog Stereo [vol: 1.00]
...
Finally, use your desktop environments audio settings panel to select your AirPlay receiver as audio output device.