- Shell 59.4%
- Makefile 40.6%
| diy-babycam-audio-watch.service | ||
| diy-babycam-audio-watch.sh | ||
| diy-babycam-stream.service | ||
| diy-babycam-stream.sh | ||
| diy-babycam.default | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
diy-babycam
A minimal baby camera setup using a USB webcam and microphone on Linux. Two systemd services handle the video stream and audio alerting:
- diy-babycam-stream — streams webcam video + audio over HTTP using VLC (
cvlc) - diy-babycam-audio-watch — monitors mic volume and sends a push notification via ntfy.sh when the baby is loud
Dependencies
Install these before proceeding:
# Debian/Ubuntu
sudo apt install vlc-bin sox curl pipewire-audio-client-libraries
# Fedora
sudo dnf install vlc sox curl pipewire-utils
The pw-record binary (from PipeWire) and cvlc (VLC headless) are required at runtime.
Hardware
- Any USB webcam that exposes a V4L2 device (e.g.
/dev/video0) - Any USB microphone or webcam with a built-in mic visible as a PulseAudio/PipeWire source
Finding your audio device name
The scripts need the PipeWire/PulseAudio source name for your microphone, not a human-readable label.
List all audio input sources (microphones):
pactl list sources short
Example output:
0 alsa_output.pci-0000_00_1f.3.analog-stereo.monitor ... SUSPENDED
1 alsa_input.usb-HK-5693-201123_HA501_01.00.00-02.analog-stereo ... SUSPENDED
The name in the second column is what you need. Ignore entries ending in .monitor — those are loopback captures of outputs, not real microphones.
For more detail (human-readable description alongside the name):
pactl list sources | grep -E '^\s*(Name|Description):'
Or with PipeWire's native tool:
pw-cli ls Node | grep -E '(node\.name|node\.description|media\.class)' | paste - - -
Filter to just input devices:
pw-cli ls Node | grep -B1 -A2 'Audio/Source'
Once you have the name, plug it into the config file below.
Configuration
All site-specific values are kept in /etc/default/diy-babycam. The make install step creates this file from the template if it does not already exist. Edit it before enabling the services:
sudo nano /etc/default/diy-babycam
| Variable | Required | Description |
|---|---|---|
BABYCAM_AUDIO_DEVICE |
yes | PipeWire/PulseAudio source name for the microphone |
BABYCAM_VIDEO_DEVICE |
no | Webcam device node (default: /dev/video0) |
BABYCAM_NTFY_URL |
yes | Full ntfy.sh channel URL, e.g. https://ntfy.sh/my-channel |
BABYCAM_THRESHOLD |
no | RMS amplitude trigger level, 0.0–1.0 (default: 0.015) |
BABYCAM_COOLDOWN |
no | Seconds between repeat alerts (default: 10) |
BABYCAM_SAMPLE_SECONDS |
no | Audio measurement window in seconds (default: 0.3) |
Example /etc/default/diy-babycam:
BABYCAM_AUDIO_DEVICE="alsa_input.usb-HK-5693-201123_HA501_01.00.00-02.analog-stereo"
BABYCAM_VIDEO_DEVICE="/dev/video0"
BABYCAM_NTFY_URL="https://ntfy.sh/my-nursery-alerts"
BABYCAM_THRESHOLD="0.020"
BABYCAM_COOLDOWN="15"
Installation
These are user systemd services — they run inside your login session so they have access to PipeWire/PulseAudio. The install step (needs root) places files in system directories; the enable step runs as your normal user.
# 1. Install scripts to /usr/local/bin and unit files to /etc/systemd/user (needs root)
sudo make install
# 2. Edit the config with your device names and ntfy URL
sudo nano /etc/default/diy-babycam
# 3. Enable and start both services — run as your user, NOT root
make enable
To have the services start at boot even without an interactive login (headless/server use), enable lingering for your user:
sudo loginctl enable-linger $USER
To stop and disable (run as your user):
make disable
To uninstall scripts and unit files (run as root; config file is left in place):
sudo make uninstall
Watching the stream
Once running, the video stream is available at:
http://<hostname>:8080/stream
Open it in VLC, a browser, or any player that supports MPEG-TS over HTTP:
vlc http://babycam.local:8080/stream
Viewing logs
Because these are user services, pass --user to journalctl:
journalctl --user -u diy-babycam-stream -f
journalctl --user -u diy-babycam-audio-watch -f
Tuning the alert threshold
The BABYCAM_THRESHOLD value is an RMS amplitude from 0.0 to 1.0. Typical values:
0.010— very sensitive (picks up light sounds)0.015— default, suitable for a quiet room0.030— less sensitive, requires louder crying
To observe live amplitude values, run the script directly in a terminal and watch the output.
Why brief sounds may not trigger alerts
RMS amplitude averages energy over the measurement window (BABYCAM_SAMPLE_SECONDS). A snap or short cry lasting 50–100 ms gets diluted by the surrounding silence in a 1-second window, cutting the measured value by 3–4×. The default 0.3 s window is short enough to catch transients while still being stable for sustained sounds. If you are still missing brief sounds, lower BABYCAM_SAMPLE_SECONDS to 0.1 or 0.2.
A useful way to calibrate is to measure a few representative sounds manually:
# Single 0.3-second sample
pw-record --target "$BABYCAM_AUDIO_DEVICE" --rate 48000 --channels 2 - 2>/dev/null | \
sox -t raw -r 48000 -e signed -b 16 -c 2 - -n trim 0 0.3 stat 2>&1 | \
grep "RMS amplitude"
Set BABYCAM_THRESHOLD to a value between your quiet-room baseline and the sound you want to detect.