bubblegum and duct tape
  • Shell 59.4%
  • Makefile 40.6%
Find a file
2026-05-01 23:52:02 -04:00
diy-babycam-audio-watch.service more for the audio-watcher... 2026-05-01 23:31:34 -04:00
diy-babycam-audio-watch.sh add debug flag 2026-05-01 23:52:02 -04:00
diy-babycam-stream.service troubleshooting headless pipewire ... 2026-05-01 13:23:59 -04:00
diy-babycam-stream.sh just write the code 2026-05-01 11:20:19 -04:00
diy-babycam.default audio-watch: dialing in the alert 2026-05-01 23:15:52 -04:00
LICENSE Initial commit 2026-05-01 13:48:47 +00:00
Makefile Makefile: boilerplate checks 2026-05-01 13:32:02 -04:00
README.md audio-watch: dialing in the alert 2026-05-01 23:15:52 -04:00

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.01.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 room
  • 0.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 50100 ms gets diluted by the surrounding silence in a 1-second window, cutting the measured value by 34×. 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.