notes: done 状态也能 ↻ 重跑;有 transcript 自动跳过 ASR 只重跑 LLM
deploy notes / build-and-deploy (push) Successful in 1m40s
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:
@@ -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">
|
||||
|
||||
+30
-20
@@ -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);
|
||||
|
||||
// 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 {
|
||||
|
||||
Reference in New Issue
Block a user