From 59ef87ec13235c64552def881d51cc7356dea4e9 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 15 Aug 2026 18:12:26 +0800 Subject: [PATCH] =?utf8?q?fix:=20TTS=20=E5=A2=9E=E5=8A=A0=E7=99=BE?= =?utf8?q?=E5=BA=A6=E7=BF=BB=E8=AF=91=E5=85=9C=E5=BA=95=EF=BC=8C=E8=A6=86?= =?utf8?q?=E7=9B=96=E6=9C=89=E9=81=93=E6=97=A0=E6=B3=95=E5=90=88=E6=88=90?= =?utf8?q?=E7=9A=84=E7=9F=AD=E8=AF=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 有道 dictvoice 对词库中约 45% 的短语词(41/92)返回 500, 导致这些短语学习时无音频。后端 get_tts 改为先试有道, 失败(URLError / 空响应 / JSON 错误)时回退百度翻译 TTS (本机可达,无需 key),同源缓存。已验证端到端 :8443 正常。 --- backend/main.py | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/backend/main.py b/backend/main.py index f4b5e9c..49f93c5 100644 --- a/backend/main.py +++ b/backend/main.py @@ -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: -- 2.43.0