A reliable solution for streaming audio over the network using PulseAudio's native protocol. This project provides both server and client components with proper configuration management, health monitoring, and packaging for Fedora (RPM) and Debian/Ubuntu (DEB).
- TCP Server: Hosts PulseAudio native protocol over TCP
- Configuration Management: JSON-based configuration with automatic defaults
- Security: IP ACL support and authentication options
- Health Monitoring: Automatic PulseAudio connection monitoring
- Firewall Integration: Includes firewalld service definition
- Graceful Shutdown: Proper module cleanup on service stop
- Multi-Server Support: Connect to multiple servers simultaneously
- Auto-Reconnection: Automatic reconnection with configurable retry logic
- Health Monitoring: Connection and PulseAudio health checks
- Custom Sink Names: Configurable sink names and descriptions
- Graceful Degradation: Continues operating even if some servers are unavailable
pulseaudio-network/
├── src/
│ ├── pulseaudio-network-server # Python server script
│ └── pulseaudio-network-client # Python client script
├── systemd/
│ ├── pulseaudio-network-server.service # Systemd user service for server
│ └── pulseaudio-network-client.service # Systemd user service for client
├── config/
│ ├── server.json # Default server configuration
│ └── client.json # Default client configuration
├── firewalld/
│ └── pulseaudio-network.xml # Firewalld service definition
├── rpm/
│ ├── pulseaudio-network-server.spec # RPM spec file for server
│ └── pulseaudio-network-client.spec # RPM spec file for client
├── debian/
│ ├── server/ # Debian packaging files for server
│ │ ├── control
│ │ ├── rules
│ │ ├── postinst
│ │ ├── prerm
│ │ ├── postrm
│ │ ├── changelog
│ │ ├── compat
│ │ └── copyright
│ └── client/ # Debian packaging files for client
│ ├── control
│ ├── rules
│ ├── postinst
│ ├── prerm
│ ├── changelog
│ ├── compat
│ └── copyright
├── scripts/
│ ├── build-rpm.sh # Build RPM packages
│ ├── build-deb.sh # Build DEB packages
│ └── install.sh # Install from source
├── README.md
└── LICENSE
# Build packages
./scripts/build-rpm.sh
# Install server
sudo dnf install build/server/rpmbuild/RPMS/noarch/pulseaudio-network-server-*.rpm
# Install client
sudo dnf install build/client/rpmbuild/RPMS/noarch/pulseaudio-network-client-*.rpm# Build packages
./scripts/build-deb.sh
# Install server
sudo dpkg -i build-deb/server/pulseaudio-network-server_*.deb
sudo apt-get install -f # Fix dependencies if needed
# Install client
sudo dpkg -i build-deb/client/pulseaudio-network-client_*.deb
sudo apt-get install -f # Fix dependencies if needed# Install both server and client
./scripts/install.sh
# Install only server
./scripts/install.sh server
# Install only client
./scripts/install.sh clientEdit ~/.config/pulseaudio-network/server.json:
{
"port": 4656,
"listen_address": "0.0.0.0",
"auth_anonymous": true,
"auth_ip_acl": ["192.168.1.0/24"],
"sample_spec": null,
"channel_map": null
}Configuration Options:
port: TCP port to listen on (default: 4656)listen_address: Address to bind to (default: "0.0.0.0" for all interfaces)auth_anonymous: Allow anonymous connections (default: true)auth_ip_acl: List of allowed IP addresses/subnets (empty = allow all)sample_spec: Custom sample specification (e.g., "s16le 44100 2")channel_map: Custom channel map (e.g., "front-left,front-right")
Edit ~/.config/pulseaudio-network/client.json with named configurations:
{
"default": {
"servers": [
{
"host": "192.168.1.100",
"port": 4656,
"sink_name": "network_sink_main",
"sink_description": "Main Network Audio Sink"
}
],
"auto_connect": true,
"retry_interval": 10,
"max_retries": -1
},
"office": {
"servers": [
{
"host": "office-audio.local",
"port": 4656,
"sink_name": "office_speakers",
"sink_description": "Office Speakers"
},
{
"host": "office-backup.local",
"port": 4656,
"sink_name": "office_backup",
"sink_description": "Office Speakers (Backup)"
}
],
"auto_connect": true,
"retry_interval": 5,
"max_retries": 10
},
"home": {
"servers": [
{
"host": "192.168.1.50",
"port": 4656,
"sink_name": "home_stereo",
"sink_description": "Home Stereo System"
}
],
"auto_connect": true,
"retry_interval": 15,
"max_retries": -1
}
}New Configuration Format:
- Named Configurations: Each top-level key is a configuration name
- Multiple Instances: Run different configs simultaneously with systemd templates
- Backwards Compatibility: Old format is automatically migrated
- Unique Sink Names: Each config gets unique sink names to avoid conflicts
-
Install and configure firewall (if using firewalld):
sudo firewall-cmd --permanent --add-service=pulseaudio-network sudo firewall-cmd --reload
-
Enable and start the service:
systemctl --user enable pulseaudio-network-server.service systemctl --user start pulseaudio-network-server.service -
Check status:
systemctl --user status pulseaudio-network-server.service journalctl --user -u pulseaudio-network-server.service
-
Create and configure multiple setups:
# Create sample configuration with multiple named configs pulseaudio-network-client-config create-sample # List available configurations pulseaudio-network-client-config list # Validate a specific configuration pulseaudio-network-client-config validate office
-
Enable specific configurations:
# Enable default configuration pulseaudio-network-client-config enable default # Enable office configuration pulseaudio-network-client-config enable office # Enable home configuration pulseaudio-network-client-config enable home
-
Alternative: Use systemd directly:
# Enable template service for specific config systemctl --user enable pulseaudio-network-client@office.service systemctl --user start pulseaudio-network-client@office.service # Enable multiple configurations systemctl --user enable pulseaudio-network-client@default.service systemctl --user enable pulseaudio-network-client@home.service
-
Check status and manage:
# Check status of specific configuration pulseaudio-network-client-config status office # List all client services pulseaudio-network-client-config services # Disable a configuration pulseaudio-network-client-config disable office
- Simultaneous Connections: Connect to office, home, and studio servers at once
- Context Switching: Enable/disable configs based on location or use case
- Isolated Management: Each config has its own service, logs, and lifecycle
- Template Services: Use systemd template syntax:
@configname.service
- Verify sinks are available:
pactl list sinks short
Once the client is connected, network sinks will appear in your audio settings:
- GNOME: Settings → Sound → Output Device
- KDE: System Settings → Audio → Playback Devices
- Command line:
pactl set-default-sink network_sink_main
You can also route specific applications:
# Route Firefox audio to network sink
pactl move-sink-input $(pactl list sink-inputs short | grep firefox | cut -f1) network_sink_mainService fails to start:
# Check if PulseAudio is running
pactl info
# Check for port conflicts
sudo netstat -tlnp | grep :4656
# View detailed logs
journalctl --user -u pulseaudio-network-server.service -fFirewall blocking connections:
# Check firewall status
sudo firewall-cmd --list-services
sudo firewall-cmd --list-ports
# Temporarily disable firewall for testing
sudo systemctl stop firewalldCannot connect to server:
# Test network connectivity
telnet SERVER_IP 4656
# Check DNS resolution
nslookup SERVER_HOSTNAME
# Test with minimal config
echo '{"servers":[{"host":"SERVER_IP","port":4656}]}' > ~/.config/pulseaudio-network/client.jsonSinks not appearing:
# Refresh PulseAudio
pulseaudio -k
pulseaudio --start
# Check module status
pactl list modules short | grep tunnel- Systemd logs:
journalctl --user -u pulseaudio-network-{server,client}.service
// server.json - for high-quality audio
{
"sample_spec": "s24le 96000 2",
"channel_map": "front-left,front-right"
}// client.json - reduce retry interval for faster reconnection
{
"retry_interval": 5,
"servers": [...]
}- Use IP ACLs to restrict access:
"auth_ip_acl": ["192.168.1.0/24"] - Consider VPN for internet connections
- Disable anonymous auth if not needed:
"auth_anonymous": false
- Services run as user (not root)
- Systemd security features enabled (NoNewPrivileges, ProtectSystem, etc.)
- Minimal required permissions
# Fedora/RHEL/CentOS
sudo dnf install python3 python3-devel systemd-rpm-macros rpm-build
# Debian/Ubuntu
sudo apt install python3 python3-dev debhelper dh-python dpkg-dev# Build RPM packages
./scripts/build-rpm.sh
# Build DEB packages
./scripts/build-deb.sh
# Build specific package type
./scripts/build-rpm.sh server # Only server RPM
./scripts/build-deb.sh client # Only client DEB# Start server manually
python3 src/pulseaudio-network-server
# Start client manually
python3 src/pulseaudio-network-client
# Test with custom config
CONFIG_DIR=/tmp/test-config python3 src/pulseaudio-network-server# Test package installation
sudo rpm -i build/server/rpmbuild/RPMS/noarch/pulseaudio-network-server-*.rpm
systemctl --user start pulseaudio-network-server.service
# Test service functionality
pactl list modules short | grep native-protocol-tcp// Bind to specific interface
{
"listen_address": "192.168.1.100",
"port": 4656
}// High-quality audio
{
"sample_spec": "float32le 192000 8",
"channel_map": "front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right"
}// Connect to multiple servers for redundancy
{
"servers": [
{"host": "audio1.local", "port": 4656, "sink_name": "primary"},
{"host": "audio2.local", "port": 4656, "sink_name": "secondary"}
],
"retry_interval": 5
}MIT License - see LICENSE file for details.
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Make changes and test thoroughly
- Submit a pull request
- Issues: Report bugs and feature requests on GitHub
- Documentation: Check the project wiki for detailed guides
- Community: Join discussions in the project forums
- Initial release
- Basic server and client functionality
- RPM and DEB packaging
- Systemd integration
- Configuration file support
- Health monitoring and auto-reconnection