Add Docker support, fix stale docs, translate UI to English
- 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)
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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 `arecord` subprocess (the only backend)
|
||||
- **ALSAStream** — Context manager that wraps an `arecord` subprocess 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 `arecord` as a subprocess; raw PCM is read in 100 ms chunks via a reader thread
|
||||
- Device selection: `default`, `monitor` (loopback), partial name match, or exact `hw:X,Y` ID
|
||||
- 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 Docker `docker compose down` shuts down cleanly
|
||||
|
||||
## Configuration
|
||||
|
||||
Copy `config.example.ini` to `config.ini`. Each section defines a recording source:
|
||||
- `type = stream` — HTTP/Icecast stream recording
|
||||
- `type = 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` — runs `isr.py`, maps `/dev/snd` for ALSA access
|
||||
- `web` — runs `web.py`, read-only access to recordings, exposes port 8080
|
||||
Reference in New Issue
Block a user