Added individual volume control for each sound type:
- Greeting volume (for welcome messages)
- Button sound volume (for extra button during recording)
- Beep volume (for recording start indicator)
Backend changes:
- Added volume_greeting, volume_button, volume_beep to config
- New getter/setter methods for each volume type
- API endpoints: /api/volume/greeting, /api/volume/button, /api/volume/beep
- Updated play_sound_file() with volume_override parameter
- Greeting, button, and beep playback now use their specific volumes
Frontend changes (template v1.7.0):
- Replaced single volume slider with three separate sliders
- Clean UI with labeled controls for each sound type
- Helper function setupVolumeSlider() for DRY code
- Real-time updates with debouncing (300ms)
- Visual feedback with gradient background
Config changes:
- Added volume_greeting: 70 (default)
- Added volume_button: 70 (default)
- Added volume_beep: 70 (default)
- Backward compatible with existing configs
This allows independent control of each sound's loudness,
useful when greeting needs to be louder than beep, etc.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
- Update default sample rate from 44.1kHz to 48kHz (more professional standard)
- Add sample rate validation in play_sound_file()
- Display clear warning when uploaded file doesn't match configured rate
- Update default sound generation (dial tone & beep) to use configured RATE
- Prevent playback of incompatible sample rates (avoids ALSA errors)
Error Handling:
- Check file sample rate before attempting playback
- Print warning with actual vs expected sample rate
- Return False and skip playback if mismatch detected
- User-friendly error message with resampling instructions
This fixes the "Invalid sample rate" error when playing files with
non-matching sample rates. Users must now resample their audio files
to match the configured rate (default 48kHz).
To resample audio files:
ffmpeg -i input.wav -ar 48000 output.wav
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Backend:
- Add beep_sound and beep_enabled configuration options
- Generate default 1000Hz beep (0.5s) on first run
- Add get/set methods for beep sound and enabled state
- Play beep after greeting, before recording starts
- Add /set_beep_sound and /api/beep_enabled endpoints
Frontend:
- Add "Recording Beep" toggle checkbox in settings
- Add "📣 Set Beep" button for each greeting sound
- Show beep status indicator on sounds
- Real-time enable/disable with visual feedback
- Template v1.4.0
Configuration:
- beep_sound: WAV filename for beep (default: "beep.wav")
- beep_enabled: true/false to enable/disable beep
This gives guests a clear audio cue that recording has started.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**USB Backup Features:**
- Automatic backup to multiple USB drives
- CRC32 checksum verification for data integrity
- Configurable backup paths in config.json
- Backup on write (recordings and greeting uploads)
- Corrupted backups automatically deleted
- Web interface for monitoring and testing
**Configuration:**
- Added backup section to config.example.json
- enabled: Enable/disable USB backup
- usb_paths: Array of USB mount points
- verify_crc: Enable CRC32 verification
- backup_on_write: Backup immediately after file write
**CRC32 Implementation:**
- calculate_crc32(): Compute file checksum
- 64KB chunk reading for memory efficiency
- Source and destination file verification
- Automatic cleanup of failed copies
**Backup Functions:**
- backup_file_to_usb(): Backup with verification
- get_usb_backup_status(): Check drive status
- Mount detection, write test, free space check
- Preserves directory structure on USB
**Web Interface:**
- USB Backup card with drive status display
- Green/Yellow/Red status indicators
- Free space monitoring
- Test backup button
- Real-time status refresh
- Detailed error reporting
**Integration:**
- Recordings backed up after save
- Greetings backed up after upload
- Backup results logged to console
- Non-blocking backup execution
**API Endpoints:**
- GET /api/backup/status - Drive status
- POST /api/backup/test - Test backup
**Documentation:**
- Complete USB backup guide in README
- Mount instructions for USB drives
- CRC verification explanation
- Backup directory structure
- Web interface usage guide
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Breaking Behavior Change:
- Extra button NOW only works when handset is OFF-hook (during call)
- Previous: worked when on-hook (idle) - REVERSED
- Reason: Button is for guests to trigger during their call/recording
New Feature - Greeting Delay:
- Add greeting_delay_seconds to config.json (0-10 seconds)
- Delays greeting playback after handset pickup
- Gives guests time to position phone comfortably
- Default: 0 (plays immediately, backward compatible)
Extra Button Logic:
- Only responds when phone_status == "off_hook"
- Ignored when phone is on-hook (idle)
- Can be pressed during greeting or recording
- Plays entire sound without interruption
- Useful for: "Press button to hear special message"
Greeting Delay Use Cases:
- Wedding: Give guests moment to settle in
- Events: Time to position phone comfortably
- Accessibility: Extra time for elderly guests
- Professional: Pause before message delivery
Configuration:
{
"system": {
"greeting_delay_seconds": 2, // 2 second pause
"extra_button_sound": "surprise.wav"
}
}
Console Output:
- "Extra button ignored - phone is on hook" (when idle)
- "Waiting X seconds before greeting..." (delay active)
- "=== Extra button pressed ===" (during call)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Features:
- Configurable extra button on any GPIO pin
- Upload and select custom sound for button press
- Non-blocking button operation (separate thread)
- Debounced to prevent double-triggers (0.5s)
- Works independently from phone handset
- Can be pressed anytime, even during recording
Configuration:
- gpio.extra_button_enabled: Enable/disable feature
- gpio.extra_button_pin: GPIO pin number (default: 27)
- gpio.extra_button_pressed_state: "LOW" or "HIGH"
- system.extra_button_sound: Default sound file
Web Interface:
- Display active button sound in alert
- "🔘 Set Button" action on greeting items
- Visual indicator (🔘) for active button sound
- Upload any WAV file and assign to button
- Play/preview button sounds in browser
Backend:
- RotaryPhone.play_extra_button_sound() method
- RotaryPhone.set_extra_button_sound() method
- Thread-based playback to not block main loop
- /set_extra_button_sound API endpoint
- Extra button sound tracked in user_config.json
Documentation:
- Extra button setup in README
- Configuration examples
- GPIO pin configuration
- Operation workflow
Use Cases:
- Play special message on button press
- Sound effects for wedding games
- Multiple interaction points
- Custom audio triggers
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Breaking Changes:
- Configuration now via config.json instead of editing Python code
- Remove all hardcoded paths (no more /home/berwn)
- Separate system config (config.json) from runtime config (user_config.json)
Features:
- config.example.json with all configurable options
- GPIO pin and state configuration
- Audio device index configuration
- Customizable paths (relative or absolute)
- Web port and upload size settings
- No code editing required for deployment
Configuration Structure:
- gpio: hook_pin, hook_pressed_state
- audio: device_index, chunk_size, channels, sample_rate, max_record_seconds
- paths: base_dir, recordings_dir, sounds_dir
- web: port, max_upload_size_mb
- system: active_greeting, default_volume
Script automatically:
- Checks for config.json on startup
- Provides helpful error if missing
- Uses relative paths by default
- Loads test_complete.py config from same file
Updated Documentation:
- Complete configuration guide in README
- Setup instructions without hardcoded paths
- Troubleshooting for config errors
- Device index discovery command
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>