Headless Dual-Mono Audio + PTZ Video Recording System for Raspberry Pi
A professional-grade dual-channel audio and video recording system with web-based scheduling and management for Raspberry Pi. Supports Behringer UCA202 USB audio interface and PTZOptics cameras for synchronized A/V capture. Designed for church services and similar recurring event recording.
- Dual-mono capture (48kHz, 16-bit WAV, independent channels)
- Manual start/stop from Dashboard
- Configurable recording filenames with customizable channel suffixes
- Human-readable filename format:
YYYY_MMM_DD_HH:MM_L.wav - 4-hour duration limit with override option
- Pre-flight disk space checking
- Automatic post-recording analysis (silence detection, dB levels)
- Audio artifact detection (digital clipping, upstream/analog flat-top clipping, discontinuities)
- Traffic-light quality badges on Recordings page (green/yellow/red)
- Interactive analysis modal showing per-channel metrics and quality details
- Section tagging during recording (mark beginning/ending of segments for post-processing)
- PTZOptics camera integration for synchronized A/V capture
- RTSP stream capture using FFmpeg with
-c copy(zero CPU re-encoding) - Hardware-accelerated transcoding using
h264_v4l2m2m(Raspberry Pi GPU) - 10 customizable PTZ preset buttons with user-defined labels
- Automatic post-processing: raw files saved to
/raw/, transcoded to/processed/ - Real-time transcode progress tracking with percentage display
- USB storage validation with mount point checking
- Live stream viewing with copyable ffplay/VLC commands
- One-time scheduled recordings
- Recurring schedules (daily, weekly, monthly patterns)
- Multi-week calendar view
- Click calendar days to create schedules instantly
- Optional video capture with audio schedules
- Schedule page with calendar view and instant scheduling
- New/In Progress page for unified recording controls
- Recordings page with audio and video file browser
- Settings page with audio and camera configuration
- Visual directory browser for storage path selection with folder creation
- Visual calendar with color-coded events
- Live date/time display on all pages
- Disk space monitoring in navigation ribbon
- Complete backup/restore system
- User authentication with login/logout
- Role-based permissions (Viewer, Operator, Admin)
- Auto-start service (systemd)
- Automated installation script with upgrade support
- Automatic audio device detection
- Schedule persistence across reboots
- Export/import configuration and schedules
- Dedicated log files for recorder, scheduler, and FFmpeg
- Log viewer in Settings with selectable log type and file path display
- System state logging at recording start (environment, ALSA state)
- 60-second heartbeat during recordings
- FFmpeg stderr capture for debugging
- Troubleshooting script for diagnosing scheduled recording issues
- Raspberry Pi: Pi 3B/3B+ or Pi 4 (2GB+ RAM recommended)
- Audio Interface: Behringer UCA202 or UCA222 USB
- Storage: 32GB+ SD card (Class 10 or better)
- Power Supply: 5V/2.5A (Pi 3) or 5V/3A (Pi 4)
- Network: Ethernet or WiFi connection
- PTZ Camera: PTZOptics camera with HTTP CGI support and RTSP streaming
- USB Storage: External USB drive for video files (mounted at
/mnt/usb_recorder) - Network: Camera and Pi must be on same network for RTSP access
- OS: Raspberry Pi OS Lite (64-bit) - Trixie (Debian 13) recommended
- Alternative: Bookworm (Debian 12) also supported
- Download: https://www.raspberrypi.com/software/operating-systems/
- Image: "Raspberry Pi OS Lite (64-bit)" - No desktop environment
cd ~
git clone https://github.com/vilpter/ilc-Audio-Recorder.git audio-recorder
cd audio-recorder
./install.shcd ~/audio-recorder
git pull
./install.sh
# Select "Upgrade" when promptedAccess web interface at: http://<raspberry-pi-ip>:5000
The installer handles:
- System dependencies (Python, FFmpeg, ALSA, SQLite)
- Python packages
- ALSA configuration
- Recordings directory
- Systemd service setup
- Log directories
Upgrade Mode preserves your ALSA config, udev rules, and service customizations.
If you prefer manual installation or the installer encounters issues:
sudo apt update && sudo apt upgrade -ysudo apt install -y python3-pip ffmpeg alsa-utils sqlite3 gitcd ~/audio-recorder
pip3 install -r requirements.txt --break-system-packagessudo cp configs/asound.conf /etc/asound.conf
sudo alsactl kill rescan
# Verify UCA202 is detected
arecord -l
# Should show: card 1: CODEC [USB Audio CODEC]mkdir -p ~/recordings
mkdir -p ~/.audio-recordersudo mkdir -p /var/log/audio-recorder
sudo chown $USER:$USER /var/log/audio-recorder
sudo cp audio-recorder.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable audio-recorder
sudo systemctl start audio-recorder- Visual multi-week calendar view
- See all upcoming recordings
- Click any day to create or edit schedules
- Option to capture video with audio schedules
- One-time and recurring recording support
- Unified recording controls: Audio Only, Video Only, or Both
- Combined audio/video status display
- Section tagging: mark beginning/ending of segments during recording
- Control PTZ camera presets (10 customizable positions)
- View video transcode progress
- Access live stream URLs for external players
- Browse all recorded audio files
- Browse raw and processed video files
- Batch select for bulk download or delete
- Download recordings as ZIP archive
- Click filenames to view audio analysis (duration, silence percentage, dB levels, clipping, discontinuities)
- Section tags displayed in analysis modal for post-processing reference
- Traffic-light quality badges for at-a-glance audio health overview
- Configure audio device (auto-detect or manual)
- Configure PTZ camera (IP, credentials, RTSP port)
- Set PTZ preset names (e.g., "Podium", "Wide Angle")
- Configure USB storage path for video files
- Test camera connection
- Customize recording filename format
- Export/import schedules and configuration
- Database clean-up tool to remove old recording entries
audio-recorder/
├── app.py # Flask web server
├── recorder.py # Audio capture logic
├── video_recorder.py # Video capture and transcoding
├── scheduler.py # Job scheduling (APScheduler)
├── auth.py # Authentication module
├── requirements.txt # Python dependencies
├── audio-recorder.service # Systemd service file
├── install.sh # Automated installer
├── configure_audio.sh # Audio configuration helper
├── fix_service.sh # Service troubleshooting script
├── troubleshoot_audio.sh # Diagnostic script for scheduled recordings
├── audio_analyzer.py # Audio analysis module (silence detection, dB levels)
├── artifact_detector.py # Audio artifact detection (clipping, discontinuities)
├── configs/
│ ├── asound.conf # ALSA configuration
│ └── 85-usb-audio.rules # udev rules for USB audio
└── templates/ # HTML templates
├── calendar.html # Schedule page (home page with calendar)
├── camera.html # New/In Progress (recording controls)
├── recordings.html # Audio and video file browser
├── settings.html # Settings page
├── login.html # Login page
├── setup.html # Initial setup
└── change_password.html # Password change
Files are saved as dual-mono WAV files:
- Format: PCM 16-bit
- Sample Rate: 48kHz
- Channels: 2 (split into separate files)
- Naming:
YYYY_MMM_DD_HH:MM_SUFFIX.wav
Example:
2026_Jan_17_14:30_L.wav # Left channel
2026_Jan_17_14:30_R.wav # Right channel
File Size Estimates:
- ~345 MB/hour per channel
- ~690 MB/hour for both channels
- 4-hour recording ≈ 2.8 GB total
Video files are saved to USB storage (default: /mnt/usb_recorder):
/mnt/usb_recorder/
├── raw/ # Original RTSP captures (large files)
│ └── video_2026-01-24_14-30-00.mp4
└── processed/ # Transcoded files (smaller, Pi-optimized)
└── video_2026-01-24_14-30-00.mp4
- Raw Files: Direct RTSP stream copy (no re-encoding, zero CPU usage)
- Processed Files: H.264 transcoded using Raspberry Pi GPU (
h264_v4l2m2m) - Default Bitrate: 2 Mbps (configurable)
- Go to Settings page
- Enter camera IP address (e.g.,
192.168.1.100) - Enter credentials if authentication is enabled
- Configure USB storage path
- Name your PTZ presets (e.g., "Podium", "Wide Angle", "Audience")
- Click Test Connection to verify
From the Camera page, copy the stream URL for external players:
- ffplay:
ffplay rtsp://192.168.1.100:554/1 - VLC: Open Network Stream with the RTSP URL
The system auto-detects USB audio devices. Configure in Settings page:
- Auto-detect: Recommended, finds UCA202 automatically
- Manual: Select specific device if multiple audio interfaces present
Configure channel suffixes in Settings:
- Default:
LandR - Change to anything (e.g., "Left"/"Right", "Ch1"/"Ch2")
- Live preview shows expected filename format
Configure in Settings page:
- Camera IP: Network address of PTZOptics camera
- Username/Password: Optional HTTP Basic authentication
- RTSP Port: Default 554
- USB Storage Path: Mount point for video files (default
/mnt/usb_recorder) - Preset Names: Custom labels for PTZ positions 1-10
Export from Settings page:
- Schedules (.sched): All scheduled recordings
- Configuration (.conf): Audio device settings, channel suffixes, camera config
Import features:
- Two-step confirmation before overwriting
- Automatic backup before any import
- One-click revert to undo last import
# Run the fix script
./fix_service.sh
# Or manually check
sudo systemctl status audio-recorder
sudo journalctl -u audio-recorder -n 50
tail -f /var/log/audio-recorder/app.log# Run audio configuration helper
./configure_audio.sh
# Or manually check
lsusb | grep Audio
arecord -l
sudo reboot# Check if service is running
sudo systemctl status audio-recorder
# Check if port 5000 is open
sudo netstat -tlnp | grep 5000
# Test from Pi itself
curl http://localhost:5000-
Check disk space:
df -h ~/recordings -
Test FFmpeg manually:
ffmpeg -f alsa -i hw:1 -t 5 \ -filter_complex "[0:a]channelsplit=channel_layout=stereo[left][right]" \ -map "[left]" -acodec pcm_s16le -ar 48000 test_L.wav \ -map "[right]" -acodec pcm_s16le -ar 48000 test_R.wav
-
Check ALSA permissions:
groups $USER # Should include "audio"
Camera not connecting?
- Verify camera IP in Settings
- Test camera ping:
ping 192.168.1.100 - Check camera is on same network as Pi
- Verify credentials if authentication enabled
USB storage not detected?
# Check mount point exists
ls -la /mnt/usb_recorder
# Verify USB drive is mounted
df -h /mnt/usb_recorder
# Mount manually if needed
sudo mount /dev/sda1 /mnt/usb_recorderTranscoding slow or failing?
# Check hardware encoder availability
ffmpeg -encoders | grep v4l2
# Monitor transcode progress in logs
tail -f /var/log/audio-recorder/app.logRTSP stream not working?
# Test stream directly
ffplay rtsp://CAMERA_IP:554/1
# Check port is accessible
nc -zv CAMERA_IP 554| Resource | Usage | Notes |
|---|---|---|
| CPU | <5% | During recording on Pi 3/4 |
| RAM | ~100 MB | Application memory |
| Disk I/O | 384 KB/s | Sustained write rate |
| File Size | ~345 MB/hour | Per channel (WAV format) |
| Resource | Usage | Notes |
|---|---|---|
| CPU (capture) | <5% | RTSP passthrough with -c copy |
| CPU (transcode) | 10-30% | Hardware-accelerated h264_v4l2m2m |
| File Size (raw) | Varies | Depends on camera bitrate |
| File Size (processed) | ~900 MB/hour | At 2 Mbps default bitrate |
On first access, you'll be prompted to create an admin account:
- Navigate to
http://<raspberry-pi-ip>:5000 - Create username (min 3 characters) and password (min 6 characters)
- Log in with your new credentials
- Session-based authentication with Flask-Login
- "Remember me" option for persistent sessions
- Change password from Settings page
- All routes protected - login required
- Role-based access control:
- Viewer: Schedule, Control, Recordings access only
- Operator: Limited Settings (Audio/Camera config)
- Admin: Full access including user management
- Designed for local network use
- For remote access, use SSH tunneling or VPN
- Credentials stored with secure password hashing (Werkzeug)
- Session secret key auto-generated and stored in
~/.audio-recorder/
- Add configurable audio post-processing (WAV → MP3/FLAC/AAC-LC) with adjustable bitrate
- Note the last date of download for files
- Backend: Python 3.11+, Flask, Flask-Login, APScheduler
- Frontend: HTML5, Tailwind CSS, Vanilla JavaScript
- Audio: FFmpeg, ALSA
- Database: SQLite3
After completing development work, ensure the following are updated:
-
Version Numbers
- Update
__version__inapp.py - Update version at bottom of
README.md - Add entry to
CHANGELOG.md
- Update
-
Documentation
- Update
CHANGELOG.mdwith detailed changes - Update
README.mdfeatures if applicable - Update
ARCHITECTURE.mdif API or schema changed
- Update
-
Testing
- Verify Python syntax:
python3 -m py_compile app.py auth.py - Test affected functionality in browser
- Check for console errors in browser dev tools
- Verify Python syntax:
- Issues: GitHub Issues
- Quick Fixes: Run
./fix_service.shor./configure_audio.sh
Version: 1.10.0 Last Updated: 2026-02-10