notes: done 状态也能 ↻ 重跑;有 transcript 自动跳过 ASR 只重跑 LLM
deploy notes / build-and-deploy (push) Successful in 1m40s

- 前端 retry 按钮去掉 status==failed 限制,总显示(中间态 disabled)
- backend process_recording 启动时看 transcript 有没有,有就直接 cleaning 起步,
  省 30 分钟录音那个 2-3 分钟的 ASR 切片串行
This commit is contained in:
Fam Zheng
2026-05-18 01:44:11 +01:00
parent e072109e91
commit 3e478228dd
2 changed files with 36 additions and 21 deletions
+6 -1
View File
@@ -79,7 +79,12 @@
<span>{{ statusLabel(selected.status) }}</span>
<span>· {{ fmtSize(selected.size_bytes) }}</span>
<span>· {{ selected.created_at }}</span>
<button v-if="selected.status === 'failed'" class="retry-btn" @click="retry"> 重试</button>
<button
class="retry-btn"
:disabled="['pending','transcribing','cleaning','summarizing'].includes(selected.status)"
:title="selected.transcript ? '已有 transcript,只重跑 LLM 润色 + 纪要' : '重新 ASR + 润色 + 纪要'"
@click="retry"
> 重跑</button>
<button class="danger-btn" @click="remove">删除</button>
</div>
<div v-if="selected.status === 'done'" class="feishu-row">
+26 -16
View File
@@ -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<String>) = {
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<String>>(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);
// ASRmultipart POSTOpenAI Whisper 风格
let transcript = match call_asr(&s, &path, &filename).await {
Ok(t) => t,
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 {