From 3e478228dd207954ccb8a5da3b247083c2cfb5c0 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 18 May 2026 01:44:11 +0100 Subject: [PATCH] =?UTF-8?q?notes:=20done=20=E7=8A=B6=E6=80=81=E4=B9=9F?= =?UTF-8?q?=E8=83=BD=20=E2=86=BB=20=E9=87=8D=E8=B7=91=EF=BC=9B=E6=9C=89=20?= =?UTF-8?q?transcript=20=E8=87=AA=E5=8A=A8=E8=B7=B3=E8=BF=87=20ASR=20?= =?UTF-8?q?=E5=8F=AA=E9=87=8D=E8=B7=91=20LLM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 前端 retry 按钮去掉 status==failed 限制,总显示(中间态 disabled) - backend process_recording 启动时看 transcript 有没有,有就直接 cleaning 起步, 省 30 分钟录音那个 2-3 分钟的 ASR 切片串行 --- apps/notes/frontend/src/App.vue | 7 ++++- apps/notes/src/main.rs | 50 ++++++++++++++++++++------------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/apps/notes/frontend/src/App.vue b/apps/notes/frontend/src/App.vue index e263243..38b56bb 100644 --- a/apps/notes/frontend/src/App.vue +++ b/apps/notes/frontend/src/App.vue @@ -79,7 +79,12 @@ {{ statusLabel(selected.status) }} · {{ fmtSize(selected.size_bytes) }} · {{ selected.created_at }} - +
diff --git a/apps/notes/src/main.rs b/apps/notes/src/main.rs index f2d27e3..f7b6f71 100644 --- a/apps/notes/src/main.rs +++ b/apps/notes/src/main.rs @@ -436,35 +436,45 @@ async fn upload_recording( } async fn process_recording(s: AppState, id: i64) { - set_status(&s, id, "transcribing", None, None); let path = s.blobs_dir.join(id.to_string()); - let filename: String = { + // 取已有的 transcript(让 retry 跳过 ASR 直接 cleanup + summary) + let (filename, existing_transcript): (String, Option) = { let conn = s.db.lock().unwrap(); conn.query_row( - "SELECT filename FROM recordings WHERE id = ?1", + "SELECT filename, transcript FROM recordings WHERE id = ?1", params![id], - |r| r.get(0), + |r| Ok((r.get::<_, String>(0)?, r.get::<_, Option>(1)?)), ) - .unwrap_or_else(|_| "audio".to_string()) + .unwrap_or_else(|_| ("audio".to_string(), None)) }; + let has_transcript = existing_transcript + .as_deref() + .map(|t| !t.trim().is_empty()) + .unwrap_or(false); - // ASR:multipart POST,OpenAI Whisper 风格 - let transcript = match call_asr(&s, &path, &filename).await { - Ok(t) => t, - Err(e) => { - tracing::error!(%id, error = %e, "ASR failed"); - set_status(&s, id, "failed", None, Some(&format!("ASR: {e}"))); - return; + let transcript = if has_transcript { + tracing::info!(%id, "transcript exists, skip ASR"); + existing_transcript.unwrap() + } else { + set_status(&s, id, "transcribing", None, None); + match call_asr(&s, &path, &filename).await { + Ok(t) => { + let conn = s.db.lock().unwrap(); + let _ = conn.execute( + "UPDATE recordings SET transcript = ?1, status = 'cleaning' WHERE id = ?2", + params![&t, id], + ); + t + } + Err(e) => { + tracing::error!(%id, error = %e, "ASR failed"); + set_status(&s, id, "failed", None, Some(&format!("ASR: {e}"))); + return; + } } }; - // 写 transcript,进入 cleaning - { - let conn = s.db.lock().unwrap(); - let _ = conn.execute( - "UPDATE recordings SET transcript = ?1, status = 'cleaning' WHERE id = ?2", - params![&transcript, id], - ); - } + // 不管走哪条都进 cleaning + set_status(&s, id, "cleaning", None, None); // LLM cleanup:分段 + 去口语 + 润色 + 高亮(失败也继续 summary,不阻塞) match call_llm_cleanup(&s, &transcript).await {