]> acesimba.cloud Git - words.git/commitdiff
fix: TTS 增加百度翻译兜底,覆盖有道无法合成的短语
authorroot <root@localhost.localdomain>
Sat, 15 Aug 2026 10:12:26 +0000 (18:12 +0800)
committerroot <root@localhost.localdomain>
Sat, 15 Aug 2026 10:12:26 +0000 (18:12 +0800)
有道 dictvoice 对词库中约 45% 的短语词(41/92)返回 500,
导致这些短语学习时无音频。后端 get_tts 改为先试有道,
失败(URLError / 空响应 / JSON 错误)时回退百度翻译 TTS
(本机可达,无需 key),同源缓存。已验证端到端 :8443 正常。

backend/main.py

index f4b5e9c06f99657ff834d6b4fa6b095bcbda7e79..49f93c59d9aefeba298428db990649f2b1a7a8cf 100644 (file)
@@ -268,17 +268,32 @@ async def get_tts(word: str):
             data = f.read()
         return Response(content=data, media_type="audio/mpeg")
 
-    # 拉取有道 TTS(type=2 美式发音)
-    url = "https://dict.youdao.com/dictvoice?audio=" + urllib.parse.quote(word) + "&type=2"
-    req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
-    try:
-        with urllib.request.urlopen(req, timeout=10) as resp:
-            data = resp.read()
-    except urllib.error.URLError as e:
-        raise HTTPException(status_code=502, detail=f"TTS upstream error: {e}")
+    # 多源 TTS:先有道(type=2 美式),失败回退百度翻译(本机可达,可覆盖有道无法合成的短语,无需 key)
+    sources = [
+        ("youdao", "https://dict.youdao.com/dictvoice?audio=" + urllib.parse.quote(word) + "&type=2",
+         {"User-Agent": "Mozilla/5.0"}),
+        ("baidu", "https://fanyi.baidu.com/gettts?lan=en&text=" + urllib.parse.quote(word) + "&spd=3",
+         {"User-Agent": "Mozilla/5.0", "Referer": "https://fanyi.baidu.com/"}),
+    ]
+    data = None
+    last_err = None
+    for name, url, headers in sources:
+        try:
+            req = urllib.request.Request(url, headers=headers)
+            with urllib.request.urlopen(req, timeout=10) as resp:
+                ct = resp.headers.get("Content-Type", "")
+                if ct.startswith("application/json"):
+                    last_err = f"{name} returned json (no audio)"
+                    continue
+                data = resp.read()
+            if data:
+                break
+        except urllib.error.URLError as e:
+            last_err = f"{name}: {e}"
+            continue
 
     if not data:
-        raise HTTPException(status_code=502, detail="TTS empty response")
+        raise HTTPException(status_code=502, detail=f"TTS upstream error: {last_err}")
 
     # 写入缓存
     try: