Files
ISR/CLAUDE.md
T
admin 8254ccde86 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)
2026-04-26 10:56:55 +02:00

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 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