fix(gui): Recorder-Zustand nach Neuladen vom Server holen

Die GUI hielt `recording`/`recStart`/`markers` nur im Browser-State und fragte
den Server nie danach. Nach jedem F5 stand der Recorder auf 00:00, obwohl
parecord weiterlief — und das Kopfband malte den Start- statt des Stop-Knopfes,
die laufende Aufnahme war aus der GUI also nicht mehr beendbar.

`rehydrateRecording()` liest nach dem ersten render() `GET /api/health` und
stellt Laufzeit, Namensmarker und Live-Karte wieder her; Fehler bleiben still.
Nebeneffekt: ein zweites Gerät sieht die laufende Aufnahme ebenfalls.

Doku: Kapitel 03 neuer Abschnitt + /api/health in der Endpunkt-Tabelle,
Changelog-Eintrag 2026-08-10.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-10 13:18:11 +02:00
co-authored by Claude Opus 5
parent 2228c57522
commit 2be938c91b
3 changed files with 87 additions and 0 deletions
+33
View File
@@ -3,6 +3,39 @@
Chronik der Entwicklungsschritte. **Regel: jede zukünftige Änderung bekommt hier einen Eintrag** (Datum,
Was, Warum, betroffene Dateien/Backups).
## 2026-08-10 — Recorder überlebt das Neuladen (GUI holt den Zustand vom Server)
**Symptom:** während einer laufenden Aufnahme klickte der Nutzer in eine andere Aufnahme; danach stand der
Recorder auf `00:00` und zeigte den Start-Knopf — auch nach `F5`. Die Aufnahme schien gestorben.
**Sie lief die ganze Zeit.** Gemessen am Board: `parecord` PID 236484, Elternprozess = die Node-App, seit
10:59:02 UTC; die WAV wuchs um ~32 kB/s (16 kHz mono s16 = korrekt); `GET /api/health` meldete
`{"recording":true,"startedAt":1786359542932}` samt allen drei Namensmarkern.
**Ursache:** `web/src/main.js` hielt `recording`/`recStart`/`markers` ausschließlich im Browser-`state`
(Zeile 12, Startwert `false`/`0`) und fragte den Server **nie** danach — `grep -rn "api/health" web/src/`
ergab null Treffer. Jedes Neuladen setzte die GUI also auf „keine Aufnahme" zurück, obwohl `recorder.js`
weiter aufnahm. Fatal daran ist nicht die falsche Anzeige, sondern dass das Kopfband dann ● statt ■ malt:
der Stop-Knopf war unerreichbar. Immerhin ohne Datenrisiko — `recorder.js:270`
`if (current) throw new Error('already recording')` verhindert eine zweite Aufnahme über dieselbe WAV.
**Fix:** neue Funktion `rehydrateRecording()` am Ende von `main.js`, aufgerufen direkt nach dem ersten
`render()`. Sie liest `GET /api/health` und stellt `recording`, `recStart` (= `startedAt`, Server-Epoche)
und `markers` wieder her, rendert neu und frischt die Aufnahmenliste auf (Live-Karte). Ein Fehler bleibt
still (kein Toast), damit ein nicht erreichbarer Server nur die Normalansicht bedeutet. Nebeneffekt: ein
zweites Gerät sieht die laufende Aufnahme jetzt ebenfalls.
**Verifiziert:** `vite build` sauber (`dist/assets/index-B3z3XrMo.js`, `api/health` im Bundle enthalten,
`dist/index.html` verweist darauf). **Kein `systemctl restart`** — nur statische Dateien getauscht, die
laufende Aufnahme blieb unangetastet (`recording:true` vor und nach dem Build, Marker intakt).
Dateien: `app/web/src/main.js` (Board-Backups `src/main.js.bak-rehydrate`, `web/dist.bak-rehydrate`),
Kapitel 03 (neuer Abschnitt „Der Aufnahmezustand gehört dem Server" + `/api/health` in der Endpunkt-Tabelle).
⚠️ **Nebenbefund, nicht behoben:** `enroll-from-recording failed: spk beendet` bei #107 und #85 — TitaNet
stirbt im ONNX-`Where`-Knoten (`Attempting to broadcast an axis by a dimension other than 1. 12288 by
30733`), das Stimmabdruck-Lernen aus langen Aufnahmen fällt also aus. Eigener Punkt.
## 2026-08-07 (3) — Eine Person darf mehrere Namen haben (und mehrere Stimmproben)
**Warum:** die Identität war der NAME. Derselbe Mensch, in einer Aufnahme „Sascha" und in der nächsten