TTS_CACHE_DIR = os.path.join(BASE_DIR, "db", "tts_cache")
os.makedirs(TTS_CACHE_DIR, exist_ok=True)
-@app.get("/api/tts/{word}")
-async def get_tts(word: str):
+def _build_tts_response(word: str):
word = word.strip()
if not word:
raise HTTPException(status_code=400, detail="empty word")
return Response(content=data, media_type="audio/mpeg")
+
+@app.get("/api/tts/{word}")
+async def get_tts(word: str):
+ return _build_tts_response(word)
+
+
+@app.get("/api/tts")
+async def get_tts_query(w: str = ""):
+ # 含 / 的短语(如 "in the/a form of")走查询参数,避免与 URL 路径分隔符冲突
+ return _build_tts_response(w)
+
@app.post("/api/progress/update")
async def update_progress(data: ProgressUpdate):
try:
const path = url.pathname;
// 图片与 TTS 音频: cache-first (含跨域, 后端已开 CORS)
- if (path.startsWith('/api/picture/') || path.startsWith('/api/tts/')) {
+ // 注意 TTS 现用查询参数形式 /api/tts?w=,pathname 为 /api/tts(无尾斜杠),故不加尾斜杠匹配
+ if (path.startsWith('/api/picture') || path.startsWith('/api/tts')) {
event.respondWith(cacheFirst(req));
return;
}
}),
// 图片与 TTS 走 <img src>/new Audio(),不走 axios;SW 仍能拦截缓存
pictureUrl: (picId) => `${API_BASE}/api/picture/${picId}`,
- ttsUrl: (word) => `${API_BASE}/api/tts/${encodeURIComponent(word)}`,
+ // 走查询参数 w=,避免词内字面 "/"(如 "in the/a form of")与 URL 路径分隔符冲突导致 404
+ ttsUrl: (word) => `${API_BASE}/api/tts?w=${encodeURIComponent(word)}`,
};