Featured image of post PulseAudio over TCP

PulseAudio over TCP

Streaming sound from speakers using PulseAudio over the network

Introduction

PulseAudio is a sound server, in my understanding. It runs on any Linux PC. Microphones, speakers, virtual devices - everything goes through PulseAudio and is controlled by it.

Task

There’s a small server connected to a wall-mounted TV. I’m working on a PC with Manjaro and, to be honest, the headphones aren’t great. They’ll do for work, but I want to listen to music through the TV.

Sources

  1. Arch Wiki PulseAudio Examples
  2. Joao Paulo Silva de Souza’s article on Medium
  3. A good answer on Unix Overflow
  4. And another one

Solution

The traffic will be sent over TCP from the PC to the server (for simplicity, I’ll just refer to it as TV in the text, but it’s actually a server on Manjaro).

On both devices, we install the Zeroconf module so that the computers can find each other without issues.

1
yay -S pulseaudio-zeroconf

Now, let’s take the cookie file from one and copy it to the other so they are the same. I found it in my home directory on the PC.

1
2
scp ~/.config/pulse/cookie server:/etc/pulse/cookie
sudo cp -f ~/.config/pulse/cookie /etc/pulse/cookie

Now we configure:

  1. The TV will be the PulseAudio server, as it receives the audio stream.
  2. The PC will be the PulseAudio client, as it sends the stream.

On the TV, we run it as a regular user because there’s no need to start pulseaudio --kill/--start as root.

1
2
3
4
5
6
7
8
9
SUBNET='192.168.0.0/24'
sudo mkdir -p /etc/pulse/default.pa.d/
cat <<EOF | sudo tee /etc/pulse/default.pa.d/zeroconf.pa
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;${SUBNET}
load-module module-zeroconf-publish
EOF
sudo systemctl enable --now avahi-daemon.service
pulseaudio --kill
pulseaudio --start

On the PC, it’s almost the same.

1
2
3
4
5
6
7
8
9
SUBNET='192.168.0.0/24'
sudo mkdir -p /etc/pulse/default.pa.d/
cat <<EOF | sudo tee /etc/pulse/default.pa.d/zeroconf.pa
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;${SUBNET}
load-module module-zeroconf-discover
EOF
sudo systemctl enable --now avahi-daemon.service
pulseaudio --kill
pulseaudio --start

That’s it. Now in pavucontrol, you can direct some application through the tunnel to the PC!

Pavucontrol where Chrome streams directly to the TV via the server’s HDMI

Bonus that doesn’t work

What would be nice next? Right, something that won’t be useful but is interesting. I want both the PC and the TV to play the same stream.

On the PC, let’s check what outputs we have and get their names.

1
2
3
4
5
# pacmd list-sinks | grep name:
name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
name: <tunnel.aurelius.local.auto_null>
name: <tunnel.aurelius.local.auto_null.2>
name: <tunnel.aurelius.local.alsa_output.pci-0000_00_0e.0.hdmi-stereo>

Here we can see that the first one seems to be the headphones, while the others have come through the network. The 2nd and 3rd are likely the rear and front outputs on the case, while the last one is definitely the HDMI from the computer - which is what we need. So we need to combine the 1st and 4th.

Still on the PC:

1
2
3
4
5
6
7
8
9
SLAVE_1='alsa_output.pci-0000_00_1b.0.analog-stereo'
SLAVE_2='tunnel.aurelius.local.alsa_output.pci-0000_00_0e.0.hdmi-stereo'
DEFAULT_SLAVE="$SLAVE_1"
cat <<EOF | sudo tee -a /etc/pulse/default.pa.d/zeroconf.pa
load-module module-combine-sink sink_name=combined sink_properties="device.description='Combined TV and PC' slaves=${SLAVE_1},${SLAVE_2}"
set-default-sink ${DEFAULT_SLAVE}
EOF
pulseaudio --kill
pulseaudio --start

That’s it 😄 … Except it doesn’t work. I don’t know why. The device has been added, it can be selected, and there are no errors in the logs, but the sound only goes to the headphones and not to the TV. At the same time, when I simply select the TV, it works. So it seems this module cannot combine tunnel and simple devices. I decided to write this anyway; maybe it will be useful to someone.

Licensed under Apache License, Version 2.0
Last updated on Dec 10, 2024 14:01 +0200
All rights reserved
Built with Hugo
Theme Stack designed by Jimmy