8254ccde86
- Dockerfile + docker-compose.yml: two services (recorder + web) sharing ./recordings bind mount; recorder maps /dev/snd for ALSA soundcard access - requirements.txt: requests, numpy, soundfile - .dockerignore, updated .gitignore (add __pycache__, .pytest_cache) - isr.py: add SIGTERM handler for clean Docker shutdown; fix stale error message that referenced removed PulseAudio/PipeWire/PortAudio backends - web.py: translate all German UI strings to English - config.example.ini: remove PipeWire/PulseAudio/PortAudio backend refs, simplify soundcard tips to ALSA only - README.md: full rewrite as user guide (quick start, config reference, Docker notes, how it works) - CLAUDE.md: update architecture section to reflect ALSA-only backend - Delete changelog.txt and guide.md (internal session notes)
3.0 KiB
3.0 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
ISR is a Python audio recording application that captures from multiple simultaneous sources (Icecast/HTTP streams and ALSA soundcard devices) with time-based file splitting. All application code is in two files: isr.py (recorder) and web.py (archive browser UI).
Commands
# Run the recorder
python isr.py # uses config.ini
python isr.py myconfig.ini # custom config file
python isr.py --list-devices # list available ALSA devices
# Run the web UI
python web.py # http://localhost:8080
python web.py --dir recordings # custom recordings directory
# Stop: Ctrl+C (or docker compose down)
# Install dependencies
pip install requests # for stream recording
pip install numpy soundfile # for FLAC output and web waveform analysis (optional)
# Docker
docker compose up -d
docker compose logs -f
docker compose down
Architecture
Audio Backend System
- AudioDevice — Dataclass: id, name, channels, sample_rate, backend type
- AudioBackend (ABC) — Abstract base for audio capture backends
- ALSABackend — Native ALSA support via
arecordsubprocess (the only backend)
- ALSABackend — Native ALSA support via
- ALSAStream — Context manager that wraps an
arecordsubprocess and reads PCM in a thread - AudioSystem — Discovers available backends, lists devices, resolves device specs
Recorder Classes
- BaseRecorder (ABC) — Common settings,
get_next_split_time(),generate_filename(),record()interface - StreamRecorder(BaseRecorder) — Records HTTP/Icecast streams with format auto-detection and OGG/FLAC header injection
- SoundcardRecorder(BaseRecorder) — Records from ALSA devices; outputs WAV or FLAC via
_AudioFileWriter - _AudioFileWriter — Unified write/close interface for wave (WAV) and soundfile (FLAC)
- RecorderManager — Loads config, creates recorders, manages threads, handles shutdown
Key Implementation Details
- ALSA backend spawns
arecordas a subprocess; raw PCM is read in 100 ms chunks via a reader thread - Device selection:
default,monitor(loopback), partial name match, or exacthw:X,YID - Thread-safe audio buffering with
threading.Lock() - OGG/Opus/FLAC headers captured from first ~16 KB of stream and prepended to each split file
- File splits aligned to time period boundaries (
get_next_split_time()) - SIGTERM handled in
main()so Dockerdocker compose downshuts down cleanly
Configuration
Copy config.example.ini to config.ini. Each section defines a recording source:
type = stream— HTTP/Icecast stream recordingtype = soundcard— ALSA device recording
In Docker, set output_directory = /recordings and log_file = /recordings/recorder.log.
Docker
Two services share a ./recordings bind mount:
recorder— runsisr.py, maps/dev/sndfor ALSA accessweb— runsweb.py, read-only access to recordings, exposes port 8080