Namen nachtraeglich in fertige Zusammenfassung uebernehmen

speaker_labels speichert das Label jedes Clusters im LLM-Text; relabelAnalysis()
ersetzt beim Umbenennen wortgenau in summary/todos/transcript_clean und baut die
Teilnehmerliste neu. #74: keine 'Sprecher N' mehr.
This commit is contained in:
Claude
2026-07-27 23:52:28 +02:00
parent 61531fc50a
commit 448e2b0726
5 changed files with 136 additions and 8 deletions
+12
View File
@@ -15,6 +15,7 @@ export async function ensureSchema() {
ADD COLUMN IF NOT EXISTS transcript_clean TEXT NULL,
ADD COLUMN IF NOT EXISTS wav_file VARCHAR(255) NULL,
ADD COLUMN IF NOT EXISTS speaker_names TEXT NULL,
ADD COLUMN IF NOT EXISTS speaker_labels TEXT NULL,
ADD COLUMN IF NOT EXISTS analysis_status VARCHAR(16) NOT NULL DEFAULT 'pending',
ADD COLUMN IF NOT EXISTS analysis_started_at BIGINT NULL,
ADD COLUMN IF NOT EXISTS analysis_ms INT NULL`);
@@ -187,6 +188,17 @@ export async function setSpeakerName(id, speaker, name) {
if (name) m[speaker] = name; else delete m[speaker]; // empty name clears back to "Sprecher N"
await pool.execute('UPDATE recordings SET speaker_names=? WHERE id=?', [JSON.stringify(m), id]);
}
// The label EVERY speaker carried in the text the LLM produced ({speaker_07:
// "Sprecher 5"}). Stored with the analysis so a later rename can swap the name
// into the finished summary/todos instead of re-running the 20-minute analysis.
export async function setSpeakerLabels(id, labels) {
await pool.execute('UPDATE recordings SET speaker_labels=? WHERE id=?', [JSON.stringify(labels || {}), id]);
}
export async function getSpeakerLabels(id) {
const [rows] = await pool.query('SELECT speaker_labels FROM recordings WHERE id=?', [id]);
try { return JSON.parse((rows[0] && rows[0].speaker_labels) || '{}') || {}; } catch { return {}; }
}
// Seed names from acoustic identification WITHOUT clobbering existing (manual) ones.
export async function mergeSpeakerNames(id, map) {
if (!map || !Object.keys(map).length) return;