Pi doorbell PTT
Turns a Raspberry Pi into a network speaker so a phone hitting
https://doorbell.yourdomain.com can see/hear the front-door Frigate feed
and hold a button to talk through a speaker mounted at the door.
Hardware
- Any Raspberry Pi (Zero W 1st gen is enough; Zero 2 W is better for live two-way; Pi 3A+ has a 3.5mm jack onboard and skips the OTG adapter)
- Audio output, one of:
- USB speaker + micro-USB-to-USB-A OTG adapter (simplest)
- 3.5mm powered speaker (Pi 3A+ has the jack; Zero W does not)
- I2S DAC HAT (best quality, requires GPIO header)
- microSD card, power supply, WiFi or USB ethernet
Install on the Pi
# From your laptop/desktop:
scp -r pi/ pi@PI_LAN_IP:~/doorbell-src
# SSH to the Pi:
ssh pi@PI_LAN_IP
cd ~/doorbell-src
chmod +x install.sh
./install.sh
The installer apt-installs ffmpeg + alsa-utils + Python deps, creates a
virtualenv, drops server.py into ~/doorbell/, installs and enables the
systemd service, runs speaker-test to confirm ALSA output works, and
starts the service.
Verify
curl http://127.0.0.1:5555/healthz # -> ok
sudo journalctl -u doorbell -f # live logs
Wire it up
- On the Caddy host, add the
doorbell.yourdomain.comblock from../caddy/Caddyfileand reload Caddy. - DNS: point
doorbell.yourdomain.comat the Caddy host's public IP. - Open
https://doorbell.yourdomain.comon an Android phone. - Grant the one-time microphone permission.
- Tap Unmute camera if browser autoplay swallowed the audio.
- Hold the big green button to talk.
Add to home screen (Chrome menu -> Add to home screen) for an app-like experience.
Changing the camera
server.py near the top:
const CAMERA_NAME = "front_door";
After editing:
sudo systemctl restart doorbell
Audio stack
ALSA-only -- no PipeWire/PulseAudio. Lighter on the Pi Zero. If you ever
need PipeWire (e.g., to share the speaker with another app), change
'-f', 'alsa' to '-f', 'pulse' in server.py and install the
PipeWire/Pulse compatibility shim.
Troubleshooting
speaker-test fails
USB/3.5mm output isn't the default ALSA card. Check:
aplay -l
If your speaker isn't card 0, create /etc/asound.conf:
defaults.pcm.card 1
defaults.ctl.card 1
(Replace 1 with whatever card your speaker is.)
Video plays but talk button stuck on "Disconnected"
The WebSocket isn't reaching the Pi. Most common: Caddy not proxying
doorbell.yourdomain.com -> Pi correctly. From the Caddy host:
curl -i http://PI_LAN_IP:5555/healthz # should return 200 ok
Feedback loop when talking
The page auto-mutes the camera while the PTT button is held, so this should not happen. If it does, increase distance between Pi speaker and camera mic, or turn the speaker volume down.