Complete step-by-step instructions for setting up the Portable AirPlay Receiver.
- Raspberry Pi Zero 2W with Raspberry Pi OS Lite (32-bit) installed
- SSH access to the Pi
- Hardware wired according to GPIO pinout in README.md
SSH into your Pi and run these commands:
# Update system
sudo apt update && sudo apt upgrade -y
# Set timezone (adjust to your location)
sudo timedatectl set-timezone America/New_York
# Enable I2C interface
sudo raspi-config nonint do_i2c 0
# Enable SPI (needed for WS2812B)
sudo raspi-config nonint do_spi 0sudo nano /boot/firmware/config.txtAdd these lines at the end:
# I2S DAC Configuration
dtparam=i2s=on
dtoverlay=hifiberry-dac
Note: If your Pi uses /boot/config.txt instead of /boot/firmware/config.txt, use that path.
In the same file, comment out or remove:
#dtparam=audio=on
# Install build dependencies
sudo apt install -y \
build-essential \
git \
autoconf \
automake \
libtool \
libpopt-dev \
libconfig-dev \
libasound2-dev \
libavahi-client-dev \
libssl-dev \
libsoxr-dev \
libplist-dev \
libsodium-dev \
libavutil-dev \
libavcodec-dev \
libavformat-dev \
libgcrypt20-dev \
libxxhash-dev \
uuid-dev \
xmltoman \
xxd
# Install Python packages
sudo apt install -y \
python3-pip \
python3-venv \
python3-dev \
python3-smbus \
python3-pil \
i2c-tools
# Install network tools
sudo apt install -y \
hostapd \
dnsmasq \
avahi-daemoncd ~
# Install NQPTP (required for AirPlay 2)
git clone https://github.com/mikebrady/nqptp.git
cd nqptp
autoreconf -fi
./configure --with-systemd-startup
make
sudo make install
sudo systemctl enable nqptp
sudo systemctl start nqptp
cd ~
# Install Shairport Sync
git clone https://github.com/mikebrady/shairport-sync.git
cd shairport-sync
autoreconf -fi
./configure --sysconfdir=/etc --with-alsa \
--with-soxr --with-avahi --with-ssl=openssl \
--with-systemd --with-airplay-2
make
sudo make install
# Enable service
sudo systemctl enable shairport-sync
cd ~sudo nano /etc/shairport-sync.confReplace contents with:
general = {
name = "Portable AirPlay";
interpolation = "soxr";
output_backend = "alsa";
mdns_backend = "avahi";
port = 5000;
drift_tolerance_in_seconds = 0.002;
resync_threshold_in_seconds = 0.050;
volume_range_db = 60;
};
alsa = {
output_device = "hw:0";
mixer_control_name = "Digital";
mixer_device = "hw:0";
};
sessioncontrol = {
run_this_before_entering_active_state = "~/airplay/scripts/on_start.sh";
run_this_after_exiting_active_state = "~/airplay/scripts/on_stop.sh";
active_state_timeout = 10.0;
};
sudo nano /etc/asound.confAdd:
pcm.!default {
type hw
card 0
}
ctl.!default {
type hw
card 0
}
cd ~
mkdir -p airplay
cd airplay
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install Python dependencies
pip install --upgrade pip
pip install \
RPi.GPIO \
adafruit-circuitpython-ssd1306 \
adafruit-blinka \
Pillow \
rpi_ws281x \
adafruit-circuitpython-neopixel \
flask \
python-networkmanager \
alsaaudiosudo nano /etc/hostapd/hostapd.confAdd:
interface=wlan0
driver=nl80211
ssid=AirPlay-Setup
hw_mode=g
channel=7
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=0
sudo nano /etc/dnsmasq.confAdd at the end:
interface=wlan0
dhcp-range=192.168.4.2,192.168.4.20,255.255.255.0,24h
address=/#/192.168.4.1
sudo systemctl disable hostapd
sudo systemctl disable dnsmasq
sudo systemctl stop hostapd
sudo systemctl stop dnsmasqCopy the src/, templates/, and services/ directories from this repository to ~/airplay/ on your Pi.
# Copy service files
sudo cp ~/airplay/services/airplay-ui.service /etc/systemd/system/
sudo cp ~/airplay/services/wifi-portal.service /etc/systemd/system/
# Reload systemd
sudo systemctl daemon-reload
# Enable main UI service
sudo systemctl enable airplay-uimkdir -p ~/airplay/scripts
# Create playback start script
cat > ~/airplay/scripts/on_start.sh << 'EOF'
#!/bin/bash
echo "playing" > /tmp/airplay_status
EOF
# Create playback stop script
cat > ~/airplay/scripts/on_stop.sh << 'EOF'
#!/bin/bash
echo "idle" > /tmp/airplay_status
EOF
# Make executable
chmod +x ~/airplay/scripts/on_start.sh
chmod +x ~/airplay/scripts/on_stop.sh# Reboot to apply I2S config
sudo reboot
# After reboot, test audio
speaker-test -t sine -f 440 -c 2 -D hw:0
# Check ALSA devices
aplay -l
# Test Shairport Sync
sudo systemctl start shairport-sync
sudo systemctl status shairport-syncYou should now see "Portable AirPlay" in your AirPlay devices list.
# Check I2C devices
sudo i2cdetect -y 1
# Should show device at address 0x3C
# Activate virtual environment and test
cd ~/airplay
source venv/bin/activate
python3 -c "
import board
import adafruit_ssd1306
from PIL import Image, ImageDraw, ImageFont
i2c = board.I2C()
oled = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c)
oled.fill(0)
oled.show()
image = Image.new('1', (128, 64))
draw = ImageDraw.Draw(image)
draw.text((10, 25), 'Hello AirPlay!', fill=255)
oled.image(image)
oled.show()
print('Display test complete!')
"sudo rebootAfter reboot:
- OLED should show boot screen
- LED should show appropriate state
- "Portable AirPlay" should appear in AirPlay devices
- Rotary encoder should control volume
# Check if DAC is detected
aplay -l
# Should show "snd_rpi_hifiberry_dac"
# Check Shairport Sync logs
journalctl -u shairport-sync -f# Check I2C
sudo i2cdetect -y 1
# Should show 0x3C
# Check I2C is enabled
ls /dev/i2c*# Must run as root for WS2812B
sudo python3 -c "
import board
import neopixel
pixels = neopixel.NeoPixel(board.D10, 1, brightness=0.2)
pixels[0] = (0, 255, 0)
print('LED should be green')
"# Check hostapd
sudo systemctl status hostapd
sudo journalctl -u hostapd -f
# Check dnsmasq
sudo systemctl status dnsmasq