Ok, I have finally solved the issue that some (including myself) have been experiencing with PulseAudio not accepting connections. I initially had no trouble running things manually, then I tried to run with systemd unit files when I started having issues with permissions.
The key is to run your systemd units as a
user service. PulseAudio really does not like running as root, or accepting anything dealing with the root user (they REALLY discourage it in the documentation...
Whats is wrong with system mode?). Instead of creating your unit files in /etc/systemd/system, create them in /etc/systemd/user and activate them with the --user flag (see below: "
Create systemd unit for RTLSDR-Airband", "
Create systemd unit for Darkice", and "
Final Steps" <--
very important).
As a newbie to radio (and mediocre with Linux), I'm not sure I fall into a "niche" category with my setup...but I figured I'd post a tutorial for anyone else who may fall into this category.
Yes, I could have just configured RTLSDR-Airband to send audio directly to my stream with an Icecast output, I found the audio quality to be sub-par and lacked the filtering controls I wanted for cleaner audio.
Hardware: Raspberry Pi Model 4B, Nooelec NESDR SMArTee
Goal: Monitor/Broadcast a single (for now) NFM VHF frequency with a "hands-off" and headless setup.
Software: Ubuntu Server 21.04 (64bit), RTLSDR-Airband (v3.2.1), PulseAudio, DarkIce
Audio Flow: SDR --> RTLSDR-Airband (NFM) --> PulseAudio (Loopback) --> DarkIce (Loopback Monitor) --> Broadcastify
Why not Raspberry Pi Desktop or the BCFY Raspberry Pi Image? I couldn't get RTLSDR-Airband to gain access to the Raspberry Pi's GPU without running it as the root user on either of these OS images. The catch-22 here is that when running RTLSDR-Airband as root, it causes permission issues when trying to use a PulseAudio output...
There is likely a much simpler way to do this...but here we are.
Operating System Setup:
1. Use
Raspberry Pi Imager or
balenaEtcher to write Ubuntu Server to your SD Card
2. Boot up (the default username: ubuntu, password: ubuntu)
3. Get everything up-to-date by running:
sudo apt-get update && sudo apt-get upgrade -y
Install RTLSDR-Airband (Documentation):
-
Install dependencies:
sudo apt-get install build-essential libmp3lame-dev libshout3-dev libconfig++-dev libfftw3-dev librtlsdr-dev libpulse-dev libasound2 libasound2-plugins alsa-utils alsa-oss pulseaudio-utils
-
Download Code:
cd
-->
wget -O RTLSDR-Airband-3.2.1.tar.gz https://github.com/szpajder/RTLSDR-Airband/archive/v3.2.1.tar.gz
-->
tar xvfz RTLSDR-Airband-3.2.1.tar.gz
-->
cd RTLSDR-Airband-3.2.1
** Check HERE for the latest version, at the time of this post: v3.2.1 - change the version number in the commands above accordingly **
- Compile:
make PLATFORM=armv8-generic NFM=1 PULSE=1
Configure RTLSDR-Airband according to your needs:
Here is a sample:
Code:
# /usr/local/etc/rtl_airband.conf
devices: ({
type = "rtlsdr";
index = 0;
gain = 14;
centerfreq = 151.070;
correction = 0;
channels: ({
freq = 151.070;
bandwidth = 11200;
modulation = "nfm";
notch = 192.8;
outputs: ({
type = "pulse";
sink = "Loopback1";
stream_name = "County Sheriff Dispatch";
continuous = false;
})
})
})
Modify the permissions of your RTLSDR-Airband config file (we don't want to have to run as root as it causes issues when connecting to PulseAudio).
sudo chmod 777 /usr/local/etc/rtl_airband.conf
Create systemd unit for RTLSDR-Airband:
sudo nano /etc/systemd/user/rtl_airband.service
* Take note of the WantedBy change, most unit files will have multi-user.target
. For permissions and running this as a user service this should be default.target
Code:
# /etc/systemd/user/rtl_airband.service
[Unit]
Description=SDR AM/NFM demodulator
Documentation=https://github.com/szpajder/RTLSDR-Airband/wiki
Wants=network.target
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/rtl_airband -Fe
Restart=no
[Install]
WantedBy=default.target
Reload the systemctl user daemon systemctl --user daemon-reload
--> enable the service
systemctl --user enable rtl_airband.service
Configure PulseAudio:
sudo nano /etc/pulse/default.pa
Look for #load-module module-alsa-sink
and remove the leading "#"
Then add the following to the bottom of the file:
Code:
load-module module-null-sink sink_name=Loopback1
update-sink-proplist Loopback1 device.description=Loopback1
load-module module-loopback sink=Loopback1
update-source-proplist Loopback1.monitor device.description=Loopback1-Monitor
load-module module-null-sink sink_name=Loopback2
update-sink-proplist Loopback2 device.description=Loopback2
load-module module-loopback sink=Loopback2
update-source-proplist Loopback2.monitor device.description=Loopback2-Monitor
Install & Configure Darkice:
Install: sudo apt-get install darkice
Configure:
sudo nano /etc/darkice.cfg
Here is a sample config for a Broadcastify feed:
Code:
[general]
duration = 0
bufferSecs = 10
reconnect = yes
realtime = yes
[input]
device = pulseaudio
paSourceName = Loopback1.monitor
sampleRate = 22050
bitsPerSample = 16
channel = 1
[icecast2-0]
bitrateMode = cbr
format = mp3
bitrate = 16
quality = 0.1
channel = 1
lowpass = 4000
sampleRate = 22050
server = audio#.broadcastify.com
port = 80
password = hackme
mountPoint = mountpoint # do not add leading /
name = County Sheriff Dispatch
Create systemd user unit for Darkice:
sudo nano /etc/systemd/user/darkice.service
Code:
# /etc/systemd/user/darkice.service
[Unit]
Description=DarkIce live audio streamer
Documentation=http://www.darkice.org/ man:darkice(1) man:darkice.cfg(5)
Requires=sound.target
Wants=network-online.target
After=icecast.service network-online.target sound.target
[Service]
Type=simple
ExecStart=/usr/bin/darkice -c /etc/darkice.cfg
[Install]
WantedBy=default.target
Reload the systemctl user daemon
systemctl --user daemon-reload
--> enable the service
systemctl --user enable darkice.service
Final Steps:
In order for our systemd
user unit files to start at boot you should run the command:
loginctl enable-linger
which will allow the system to reboot and start your service units without actually having to login.
Reboot the system
sudo reboot now
Once the system has started up, check RTLSDR-Airband and Darkice for any errors.
RTLSDR-Airband:
systemctl --user status rtl_airband.service
Darkice:
systemctl --user status darkice.service
Hopefully...you will see something like this:
Code:
ubuntu@ubuntu:/etc$ systemctl --user status rtl_airband.service
● rtl_airband.service - SDR AM/NFM demodulator
Loaded: loaded (/etc/xdg/systemd/user/rtl_airband.service; enabled; vendor preset: enabled)
Active: active (running)
Docs: https://github.com/szpajder/RTLSDR-Airband/wiki
Main PID: 2284 (rtl_airband)
CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/rtl_airband.service
└─2284 /usr/local/bin/rtl_airband -Fe
and this:
Code:
ubuntu@ubuntu:/etc$ systemctl --user status darkice.service
● darkice.service - DarkIce live audio streamer
Loaded: loaded (/etc/xdg/systemd/user/darkice.service; enabled; vendor preset: enabled)
Active: active (running)
Docs: http://www.darkice.org/
man:darkice(1)
man:darkice.cfg(5)
Main PID: 2274 (darkice)
CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/darkice.service
└─2274 /usr/bin/darkice -c /etc/darkice.cfg
ubuntu darkice[2274]: Using config file: /etc/darkice.cfg
ubuntu darkice[2274]: Using PulseAudio audio server as input device.
ubuntu darkice[2274]: Using PulseAudio source: Loopback1.monitor
ubuntu darkice[2274]: Using POSIX real-time scheduling, priority 4
POSIX Real-Time Scheduling:
If your Darkice service throws an error saying it cannot proceed with POSIX scheduling, you'll need to do one more step to avoid skipping and repeats in your stream.
Edit the following file:
sudo nano /etc/security/limits.conf
Add the following before "# End of file":
Code:
@audio - rtprio 95
@audio - memlock unlimited
Ensure the default ubuntu user is part of the audio group:
sudo su
usermod -a -G audio ubuntu
Yes this is quite the process...thankfully the system has stayed solid through reboots so far.
Hopefully this will take down a barrier for someone else getting their stream online!