docs: update README for Docker fix, FLAC/streaming features; add README rule to CLAUDE.md

- Remove stale instruction to set output_directory = /recordings in Docker
- Document that docker compose down + up --build is required when updating
- Fix output_directory and log_file table descriptions
- Expand Web UI section: inline playback, FLAC waveform, live REC badge, WCAG
- Fix Docker notes: log_file path and log_file in Docker guidance
- Add rule to CLAUDE.md: always update and commit README.md with code changes
This commit is contained in:
2026-04-26 13:17:26 +02:00
parent da67523170
commit f84b36687b
2 changed files with 24 additions and 9 deletions
+5
View File
@@ -2,6 +2,11 @@
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Rules
- **Always update `README.md`** whenever user-facing behaviour changes (new flags, new endpoints, changed Docker setup, new features). The README is the primary external reference; CLAUDE.md documents internals.
- **Always commit `README.md`** in the same commit as the code changes it documents — never let the README fall behind.
## Project Overview ## 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). 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).
+19 -9
View File
@@ -33,19 +33,26 @@ python web.py # start web UI at http://localhost:8080
```bash ```bash
cp config.example.ini config.ini cp config.example.ini config.ini
# In config.ini set: output_directory = /recordings # edit config.ini to add your sources (no path changes needed for Docker)
# Optionally set: log_file = /recordings/recorder.log
docker compose up -d docker compose up -d
# recorder starts immediately; web UI at http://<host>:8080 # recorder starts immediately; web UI at http://<host>:8080
docker compose logs -f # tail logs from both services docker compose logs -f # tail logs from both services
docker compose down # graceful stop docker compose down # graceful stop (waits up to 30 s for files to close)
``` ```
Recordings land in `./recordings/` on the host (bind-mounted into both containers). Recordings land in `./recordings/` on the host (bind-mounted into both containers at different internal paths — no config changes required vs. bare-metal).
If you only record streams (no soundcard), comment out the `devices` block in `docker-compose.yml`. If you only record streams (no soundcard), comment out the `devices` block in `docker-compose.yml`.
**Updating a running deployment:**
```bash
git pull
docker compose down
docker compose up -d --build
```
`docker compose down` is required — Docker won't apply changed volume mounts to existing containers without recreating them.
--- ---
## Configuration ## Configuration
@@ -56,13 +63,13 @@ If you only record streams (no soundcard), comment out the `devices` block in `d
| Key | Default | Description | | Key | Default | Description |
|-----|---------|-------------| |-----|---------|-------------|
| `output_directory` | `recordings` | Output path. Use `/recordings` in Docker. | | `output_directory` | `recordings` | Output path relative to the working directory (or absolute). The Docker setup mounts `./recordings` at `/app/recordings` so this default works unchanged. |
| `split_minutes` | `60` | Split into a new file every N minutes, aligned to clock boundaries (e.g. 60 → files start at :00, 30 → at :00 and :30). | | `split_minutes` | `60` | Split into a new file every N minutes, aligned to clock boundaries (e.g. 60 → files start at :00, 30 → at :00 and :30). |
| `filename_pattern` | `%Y%m%d_%H%M%S` | strftime pattern; file extension is appended automatically. | | `filename_pattern` | `%Y%m%d_%H%M%S` | strftime pattern; file extension is appended automatically. |
| `max_retries` | `10` | Give up after this many consecutive failures per source. | | `max_retries` | `10` | Give up after this many consecutive failures per source. |
| `retry_delay_seconds` | `5` | Wait between retries. | | `retry_delay_seconds` | `5` | Wait between retries. |
| `log_level` | `INFO` | `DEBUG` / `INFO` / `WARNING` / `ERROR` / `CRITICAL` | | `log_level` | `INFO` | `DEBUG` / `INFO` / `WARNING` / `ERROR` / `CRITICAL` |
| `log_file` | `recorder.log` | Log file path. Use `/recordings/recorder.log` in Docker. | | `log_file` | `recorder.log` | Log file path. In Docker, logs also go to stdout and are visible via `docker compose logs`. |
### `type = stream` ### `type = stream`
@@ -146,9 +153,12 @@ python web.py --port 8888 # custom port
python web.py --threshold 0.03 # loudness threshold 01 (default 0.05) python web.py --threshold 0.03 # loudness threshold 01 (default 0.05)
``` ```
Shows a table of all recordings sorted newest-first with file size, duration (WAV only), and a waveform analysis button. Analysis computes RMS per 100 ms window and highlights contiguous sections above the loudness threshold. Shows a table of all recordings sorted newest-first. Features:
Waveform analysis is WAV-only; numpy speeds it up significantly (pure-Python fallback available without it). - **Inline playback** — collapsible `▶ Play` button per row; audio loads lazily via a seekable `/stream/` endpoint with HTTP Range support.
- **Waveform analysis** — on demand per file; computes RMS per 100 ms window and highlights loud sections. Supported for WAV and FLAC (FLAC requires `numpy` + `soundfile`). Pure-Python fallback for WAV when numpy is absent.
- **Live REC badge** — files currently being written by `isr.py` show an animated REC indicator, polled every 5 seconds via `/api/status`.
- **WCAG-compliant** — skip link, `aria-expanded`/`aria-controls` on the player toggle, `aria-live` status, focus management, `role=img` on SVG waveforms.
--- ---
@@ -174,7 +184,7 @@ ls -la /dev/snd # check device nodes
**Stream-only deployments:** If you don't use soundcard recording, remove the `devices` block from `docker-compose.yml` — the image works fine without it. **Stream-only deployments:** If you don't use soundcard recording, remove the `devices` block from `docker-compose.yml` — the image works fine without it.
**Log file in Docker:** Set `log_file = /recordings/recorder.log` in `config.ini` so logs survive container restarts. Alternatively, use `docker compose logs` (the recorder always logs to stdout as well). **Log file in Docker:** The recorder always logs to stdout, so `docker compose logs -f` shows live output. To persist logs on the host, set `log_file = /app/recordings/recorder.log` in `config.ini` (the `recordings` directory is the bind mount).
**File retention:** ISR never deletes recordings. Add a cron job on the host if needed: **File retention:** ISR never deletes recordings. Add a cron job on the host if needed:
```bash ```bash