feat(voice): real TTS fallback chain and whisper-compatible STT

- TTS providers: cloud (OpenAI-compatible /audio/speech, e.g. Bailian
  compatible mode with cosyvoice), local self-hosted HTTP server,
  edge-tts CLI, espeak CLI, silent — ordered by TTS_PROVIDER list,
  skipping providers whose binary/config is missing
- STT: whisper-compatible /audio/transcriptions endpoint (cloud or
  self-hosted faster-whisper), replacing the empty dashscope stub
- config: TTS_CLOUD_URL/KEY/MODEL/VOICE, TTS_LOCAL_URL, STT_API_URL/
  KEY/MODEL; cloud keys fall back to DASHSCOPE_API_KEY
- gateway /voice/tts now returns real audio/mpeg bytes instead of a
  byte count
- tests: cloud/local/whisper round-trips via httptest, chain skip
  behavior, fallback order; kept and adapted prior service tests
This commit is contained in:
Aska committed 2026-08-21 18:28:39 +08:00
1 parent b8fb7feb86
commit a0357a7bbd
7 files changed
+410 -63

No files matched your search

+7 -1
View File
@@ -476,7 +476,13 @@ func (r *Router) voiceTTSHandler(w http.ResponseWriter, req *http.Request) {
writeJSON(w, 500, M{"error": err.Error()})
return
}
writeJSON(w, 200, M{"audio_size": len(audio)})
if len(audio) == 0 {
writeJSON(w, 503, M{"error": "no tts provider available"})
return
}
w.Header().Set("Content-Type", "audio/mpeg")
w.WriteHeader(200)
w.Write(audio)
}
// --- Admin ---