Commit Graph

5 Commits

Author SHA1 Message Date
admin d7524afeff fix: disable Analyse on active recordings; guard server-side too
Clicking Analyse on a file currently being recorded caused libsndfile to
fail with 'Internal psf_fseek() failed' because an in-progress FLAC file
has no seektable (written only on close()).

Client: Analyse button is disabled with a tooltip while isRec is true.
Server: _api_analyze checks status.json and returns 409 with a readable
message if the file is still being recorded, before attempting to open it.
2026-04-26 14:44:37 +02:00
admin 357b3e6ed9 fix: reject directories in _safe_path; remove Content-Disposition from _stream
_safe_path now uses path.is_file() instead of path.exists() so empty or
directory-traversal filenames never resolve to a directory and get served
as a 0-byte octet-stream download.  This was the cause of the browser
downloading a file named 'recordings' with 0 bytes when Play was clicked.

Removed Content-Disposition: inline from _stream responses — it is not
needed for <audio> playback and it was what labelled the erroneous
directory response as 'recordings' in the save dialog.
2026-04-26 13:53:36 +02:00
admin da67523170 fix: Docker volume path, graceful shutdown deadline, inline stream headers
docker-compose.yml: mount ./recordings at /app/recordings (matches
output_directory = recordings in config.ini); previously the recorder
wrote to /app/recordings while the web container read from /recordings,
causing all files to appear missing — explaining the 9-byte Not-found
download from /stream/ and the 0-byte recordings in the UI.
Add stop_grace_period: 30s so Docker waits long enough for files to close.

isr.py: replace per-thread join(timeout=5) with a shared 25 s deadline;
with N recorders the old code could exceed Docker's SIGKILL window and
leave WAV/FLAC files unclosed (corrupt headers).

web.py: add Content-Disposition: inline to /stream/ responses so
browsers never treat the audio response as a file download.

CLAUDE.md: document web.py endpoints, status.json lifecycle, corrected
Docker volume layout, and web.py CLI flags.
2026-04-26 13:10:14 +02:00
admin 624f1f2664 feat: FLAC analysis, inline player, WCAG, live-recording status
web.py:
- Extend loudness analysis to FLAC files via soundfile (numpy required)
- Add /stream/ endpoint with HTTP Range support for seekable inline playback
- Add collapsible ▶ Play button per row (hidden by default); src loaded lazily
- Add /api/status endpoint returning active filenames from status.json
- Animated ● REC badge on in-progress files, polled every 5 s
- Full WCAG: skip link, aria-expanded/controls, aria-label, role=img on
  waveform SVG, role=list on loud-section chips, focus-visible outlines,
  aria-live on subtitle, focus moved to <audio> when player opens

isr.py:
- Write recordings/status.json atomically every 2 s while recording
- Delete status.json on clean shutdown so web UI shows no stale state
2026-04-26 12:53:01 +02:00
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