Die Identitaet war der NAME. Derselbe Mensch, einmal "Sascha" und einmal
"Sascha Wolf" benannt, existierte zweimal und konnte zwei Cluster benennen
-- Aufnahme #101 (34 s, zwei Menschen) zeigte Michael/Sascha/Sprecher 3/
Sascha Wolf. Der Vornamens-Trick in diar.js hat das ueberdeckt, setzte aber
auch "Markus Ufer" und "Markus Witsch" gleich (Kosinus 0,241).
Neu: persons + person_names (Name = PK, gehoert genau einer Person),
voiceprints.person_id. Mehrere Proben pro Person (max. 8) statt eines
laufenden Mittels; bewertet wird die beste Probe. Score UND Abstand rechnen
zwischen Personen -- vorher rissen zwei Abdruecke desselben Menschen (0,928)
die Abstandspruefung, womit die Zwangsbedingung faktisch aus war.
diar.identityKey bildet Marker-Namen und Abdruecke auf p<person_id> ab.
GUI "Stimmen" zeigt Personen mit Namens-Chips: Namen hinzufuegen/entfernen,
Personen zusammenfuehren, Proben verwerfen.
Altbestand geleert (Dump in backup/), weil lab/vpcos.mjs neben echten
Dubletten (Jens ~ Jens Kuppler = 1,000) auch kontaminierte Abdruecke zeigte:
Johannes lag mit 0,912 an Sascha Wolf, aber 0,115 an Johannes Jeckel.
Verifiziert an #101: Sascha Wolf als zweiter Name derselben Person ->
Re-Diarisierung benennt nur noch Michael + Sascha statt drei Namen fuer zwei
Menschen. GUI mit Playwright geprueft, keine JS-Fehler.
rkllm_server braucht 6,5 GB von 7,74 GB. Blieb daneben ein anderer
Dauerhelfer resident, wurde rkllm beim Laden OOM-getoetet -- bei #101 in
allen 5 Startversuchen, weil das Retry nichts freigab. Ausloeser war der
warme CT2-Whisper-Daemon, den die 2-Sekunden-Aufnahme davor gestartet
hatte. Zweiter Fall: rkllm blieb nach der Analyse fuer immer resident, und
der Suchindex startete e5-small daneben.
gate.js bekommt eine Freigabe-Registry (registerReleaser/freeRam/
killAndWait, verdrahtet in server.js wie setProbe). Vor jedem rkllm-Versuch
und vor dem NPU-Whisper-Lauf werden die anderen Helfer beendet und ihr
Prozessende abgewartet; analyzeRecording gibt rkllm vor dem Suchindex frei.
Alle Helfer starten faul neu.
Verifiziert mit der Abfolge, die scheiterte: 12-s-Clip (CT2-Daemon
resident) -> Analyse #101 laeuft durch (221 s, done), rkllm lud in 22 s,
kein OOM, danach 5,3 GB frei statt 100 MB.
identifySpeakers() embettete den laengsten Lauf ungekuerzt; TitaNet-ONNX bricht
ab 180 s ab (broadcast 12288 by 17998) und riss den spk_embed-Helfer mit. Da
spk.js die Aufrufe ueber eine Promise-Kette serialisiert, schlugen danach ALLE
weiteren Sprecher mit 'spk beendet' fehl.
- ID_CUT_SEC=25s in identifySpeakers
- Kette in spk.js und tdChain in recorder.js failure-isoliert
- pro Name gewinnt nur der beste Kosinus (Fabio war auf 2 Clustern)
#74 (22 Teilnehmer) ergab automatisch 44 Sprecher, dieselbe Stimme mehrfach.
Ursache gemessen: ein Zentroid pro sherpa-Cluster aus max. 3 Schnitten, fester
Kosinus auf rohen Embeddings (Kreuz-Turn-Kosinus ~0,4 = keine Trennschaerfe).
v2: sherpa liefert nur Turn-Grenzen, Identitaet aus 3-s-Fenster-Embeddings,
Mittelwert-Zentrierung, Average-Linkage-AHC, Weak-Fold, Schwelle pro Aufnahme
per 2-Gauss-EM gelernt. Validiert: #74 44->20, #70 ->4, #68 ->2.
Live-Namensmarker: Namen waehrend der Aufnahme tippen; Zeitstempel benennt
spaeter den Cluster und dient als must-/cannot-link-Zwangsbedingung.