ASR server 直接 500 拒绝大文件 (15MB / ~15min 4.7s 即返回 500),不是 处理超时。改成:sidecar 装 ffmpeg → /transcribe endpoint 把音频切 60s 段 → 串行调外部 ASR → 拼接 transcript。notes 主容器 call_asr 改成 POST 到 sidecar /transcribe(timeout 1h 给长录音留余地)。 - feishu sidecar Dockerfile + ffmpeg + requests - server.py 加 TranscribeReq;fallback -c copy 失败时 re-encode AAC - main.rs 删除 asr_url/asr_token 字段(now sidecar concern) - k8s manifest: ASR_URL/ASR_TOKEN 从主容器移到 feishu sidecar env
This commit is contained in:
+11
-25
@@ -31,8 +31,6 @@ struct AppState {
|
||||
db: Arc<Mutex<Connection>>,
|
||||
blobs_dir: PathBuf,
|
||||
passphrase: String,
|
||||
asr_url: String,
|
||||
asr_token: String,
|
||||
llm_gateway: String,
|
||||
llm_token: String,
|
||||
llm_model: String,
|
||||
@@ -53,9 +51,7 @@ async fn main() -> std::io::Result<()> {
|
||||
if passphrase.is_empty() {
|
||||
tracing::warn!("PASSPHRASE not set — all /api/* will return 401");
|
||||
}
|
||||
let asr_url = std::env::var("ASR_URL")
|
||||
.unwrap_or_else(|_| "http://18.159.112.195:8848/v1/audio/transcriptions".into());
|
||||
let asr_token = std::env::var("ASR_TOKEN").unwrap_or_default();
|
||||
// ASR 现在由 sidecar 调(切片串行),主容器不再直接调外部 ASR
|
||||
let llm_gateway =
|
||||
std::env::var("LLM_GATEWAY").unwrap_or_else(|_| "http://3.135.65.204:8848/v1".into());
|
||||
let llm_token = std::env::var("LLM_TOKEN").unwrap_or_default();
|
||||
@@ -95,8 +91,6 @@ async fn main() -> std::io::Result<()> {
|
||||
db: Arc::new(Mutex::new(conn)),
|
||||
blobs_dir,
|
||||
passphrase,
|
||||
asr_url,
|
||||
asr_token,
|
||||
llm_gateway,
|
||||
llm_token,
|
||||
llm_model,
|
||||
@@ -465,38 +459,30 @@ fn set_status(s: &AppState, id: i64, status: &str, transcript: Option<&str>, err
|
||||
async fn call_asr(
|
||||
s: &AppState,
|
||||
path: &std::path::Path,
|
||||
filename: &str,
|
||||
_filename: &str,
|
||||
) -> Result<String, String> {
|
||||
let bytes = tokio::fs::read(path).await.map_err(|e| e.to_string())?;
|
||||
let part = reqwest::multipart::Part::bytes(bytes)
|
||||
.file_name(filename.to_string())
|
||||
.mime_str("audio/mpeg")
|
||||
.map_err(|e| e.to_string())?;
|
||||
let form = reqwest::multipart::Form::new()
|
||||
.text("model", "qwen3-asr")
|
||||
.text("response_format", "json")
|
||||
.part("file", part);
|
||||
|
||||
// 走 sidecar /transcribe:sidecar 用 ffmpeg 切片 + 串行调外部 ASR,绕过 ASR server 单文件大小限制
|
||||
let url = format!("{}/transcribe", s.feishu_url.trim_end_matches('/'));
|
||||
let payload = json!({ "audio_path": path.to_string_lossy() });
|
||||
let resp = s
|
||||
.http
|
||||
.post(&s.asr_url)
|
||||
.bearer_auth(&s.asr_token)
|
||||
.multipart(form)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.post(&url)
|
||||
.json(&payload)
|
||||
.timeout(std::time::Duration::from_secs(3600))
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| format!("connect: {e}"))?;
|
||||
.map_err(|e| format!("connect sidecar: {e}"))?;
|
||||
if !resp.status().is_success() {
|
||||
let st = resp.status();
|
||||
let body = resp.text().await.unwrap_or_default();
|
||||
return Err(format!("ASR {st}: {body}"));
|
||||
return Err(format!("sidecar /transcribe {st}: {body}"));
|
||||
}
|
||||
let v: Value = resp.json().await.map_err(|e| format!("decode: {e}"))?;
|
||||
let text = v
|
||||
.get("text")
|
||||
.and_then(|x| x.as_str())
|
||||
.map(|s| s.to_string())
|
||||
.ok_or_else(|| format!("ASR response no 'text': {v}"))?;
|
||||
.ok_or_else(|| format!("no 'text' in response: {v}"))?;
|
||||
Ok(text)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user