Python script for a bird camera with automatic movement detection, recording and streaming. Sort of stable and ugly af right now, but seems to be working somehow (thanks ChatGPT!). After trying for weeks with ffmpeg, libcamera, picamera, frigate and whatever else Google suggested to get something coherent that can live stream and record on events with video AND audio I settled for this POS.
Client streams video and audio via an ffmpeg rtsp stream to the server.
sudo apt update
sudo apt upgrade
sudo apt install git ffmpeg
git clone https://github.com/jgrashorn/BirbCam.git
https://pypi.org/project/picamera2/
Headless version:
sudo apt install python3-picamera2 --no-install-recommends
Full installation:
sudo apt install python3-picamera2
python3 -m venv --system-site-packages /path/to/BirbCam/Camera/.venv
rename config_default.txt to config.txt
source /path/to/BirbCam/Camera/.venv/bin/activate
python /path/to/BirbCam/Camera/cameraPython.py
There are some services that can be run on both server and cameras. The respective scripts are located in the folders for camera and webapp.
It is absolutely important to keep pulseaudio running when the user is logged out if using a microphone. Otherwise the systemd-process will shut down and crash the script.
Here is what I did (I think, this is based on bash's history):
udo apt update
sudo apt upgrade
sudo apt install pulseaudio
loginctl enable-linger <userid>
sudo systemctl start user@<userid>.service
sudo -u <user> XDG_RUNTIME_DIR=/run/user/<userid> systemctl --user enable --now pulseaudio.socket pulseaudio.service
<userid> is the user's ID (id -u <user>)
libgl: sudo apt install libgl1
For rtsp-Server
https://github.com/bluenviron/mediamtx
https://pyimagesearch.com/2021/08/02/pytorch-object-detection-with-pre-trained-networks/
https://pyimagesearch.com/2019/09/02/opencv-stream-video-to-web-browser-html-page/
- Camera (Raspberry Pi + Picamera2) publishes H264 or MJPEG + audio (optional) via ffmpeg to an RTSP endpoint.
- MediaMTX receives the stream and records MP4 segments on disk.
- The Flask webapp:
- shows the live HLS stream in the browser,
- organizes recordings into per-day folders (YYYY-MM-DD),
- can export “last 60 seconds” from the current recordings via ffmpeg trim,
- runs motion detection over recorded files to produce event clips.
- Camera
- Picamera2 + FfmpegOutput → RTSP (and HLS via MediaMTX).
- Audio typically comes from PulseAudio “default” source; keep user Pulse running after logout (linger + user service).
- MediaMTX
- Records MP4 files to BIRBCAM_MEDIA_DIR//.
- Webapp (Flask)
- Templates: base.html (shared header/dark mode), camera.html (live), recordings.html (split view: player left, picker right).
- Static: style.css (dark theme), theme.js (toggle).
- Recordings organized under Webapp/recordings///.
- Motion detection
- Scans recorded MP4s, finds motion windows, trims clips using ffmpeg.
- State file .motion_state_.json keeps processed and produced lists; pruned to existing files to avoid growth.
Camera → MediaMTX (RTSP) → MP4 files on disk → Webapp:
- Live view reads HLS (m3u8) from MediaMTX.
- Recordings view lists per-day folders and plays selected MP4.
- “Save last 60s” builds a clip from the tail of the latest MP4s, with audio preserved when available.
- Existing loose MP4s are moved into per-day folders automatically by the webapp.
- UI groups by date and keeps a scrolling list of files on the right while the video player stays visible on the left.
- Camera service (systemd):
- Runs independently of SSH.
- Set XDG_RUNTIME_DIR and PULSE_SERVER for user PulseAudio if using a mic.
- Enable user lingering so Pulse persists after logout (loginctl enable-linger ).
- Motion detection timer (systemd):
- Type=oneshot service + timer (e.g., OnUnitActiveSec=5min or OnCalendar=*:0/5).
- Script uses a non-blocking lock to prevent overlapping runs.
- BIRBCAM_CAMERA: camera name (default: garten)
- BIRBCAM_MEDIA_DIR: MediaMTX recordings root (default: /home/birb/mediamtx/recordings)
- BIRBCAM_OUTPUT_DIR: Webapp outputs/recordings (default: /home/birb/BirbCam/Webapp/recordings)
- Live view HLS URLs are configured in webapp.py (cameras dict).
- Audio (camera service):
- Pulse (recommended with Picamera2’s FfmpegOutput): PULSE_SERVER=/run/user//pulse/native
- Keep Pulse alive via systemd --user and linger.
- PulseAudio is per-user; if it stops on logout and Picamera2 is bound to Pulse, audio will break. Use user lingering so Pulse stays up.
- Some USB mics are mono-only; if you test via ffmpeg/ALSA, use -ac 1 and consider plughw to handle conversion.
- Install ffmpeg and MediaMTX; confirm a working camera stream.
- Configure MediaMTX recordings directory and camera name (BIRBCAM_MEDIA_DIR, BIRBCAM_CAMERA).
- Start the Flask webapp; open / for dashboard, /camera/ for live, /recordings/ for organized clips.
- Set up systemd units for camera and motion detection, enable linger for audio stability.
- Use the “Save last 60s” button or let motion detection produce event clips automatically.
- BIRBCAM_OUTPUT_DIR: Webapp outputs