From c93b83e2cfd4c45646b80a05b748c1d13963ca07 Mon Sep 17 00:00:00 2001 From: hubian <908234780@qq.com> Date: Wed, 22 Apr 2026 18:47:03 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20ChatTTS=E9=9F=B3=E9=A2=91=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E5=90=8E=E7=AB=AF=E4=BB=A3=E7=90=86=EF=BC=8C=E8=A7=A3?= =?UTF-8?q?=E5=86=B3HTTPS=E9=A1=B5=E9=9D=A2=E8=AE=BF=E9=97=AEHTTP=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __pycache__/server.cpython-310.pyc | Bin 7307 -> 8194 bytes __pycache__/tts_service.cpython-310.pyc | Bin 8375 -> 8444 bytes logs/server.log | Bin 8257 -> 11206 bytes server.py | 30 +++++++++++++++++++++++- tts_service.py | 8 +++++-- 5 files changed, 35 insertions(+), 3 deletions(-) diff --git a/__pycache__/server.cpython-310.pyc b/__pycache__/server.cpython-310.pyc index 06ec19b664952706a3b61dbbe55954569dfd9b9d..db54a0656bd64fcc624d7f40da33c0da05bcdbd3 100644 GIT binary patch delta 3223 zcmaJ@U2Gf25x%`U{)(a~OS1lGo2D$ulqFG;Em@XjM~ZA&vK^zf&ekMqh(rnXWool^ zi8?|1Gl#SFiTZ3qqJc<^Y&6me8rYN*O{`grDrs<2UL%Pxljo1XbCg!C6Idy49AlA9 zk~q%1G(@ZEAzHJpB%&-j-@<~lc9zgOfk+)*cM<7|)lB@C>(-RSi7OIqq)m?`+Qe|& z%Ay->w0V=zFg@}}g3a1NO&dMRTIsQMnMUYwF?$kbV>HT6So5T%+|ek_s5C}99=Sl` zl;E9WCs2X~XbbJ6t%8zi8&Wee?P4ADBvY9q*-hg@vJ-aiqCK$tN!9_YdTHMy6*P8( zm8a<$u=0$sG7jT@IsoGV9G4S4!tApkI7rV41AAd6Mu%YLJd1;>VR}KR>J#%9HwhZH zh6oYeHt2<2gGT76Fz7V6a)!RhLac#~trOZ#FRd#OaSYOB&^<29?7u=Mgz|nCp_2>p zTZB)*(aM>D!~h$ZKg*)@DhtzVC`#oi@x-oMKahV_E!%-{EyHdyBd_NSW_!0Za!QA1`3@j$kHPq&mSzW~gc20BRj%vid7umxKz`^~c<)xHXO)m{>qp*bO&n&Y zV+u!g{1if`^{Mw-Bm|^gIhN5_&Yae=OfQ&XjjhfbdXC4etG=O%JzLwYZ~I;%7!qM{?P}Mmuy$6KsB8o-3t4As(m368m=KrB*%561`%FDxPh=6AO2+=-b9!}m}6)}cIcix3Q0zpFW3M(c(9v5H+6B->3{ zhM8=i=@)UGuwewLJ=4W`sv_WyHNudCyMv5f<0wt0_1q%kM#|LmoV8HfP3GWoAF+N> zyKpChx{o775n2!y5O5c9^LYj-8DTFAcCRqkfbj`D2Hq*G9|2NJxF$Aur*8TysO(0} z!z1uMxRFr0x6$*|XF=?@@a$6$#VKoz9)6butv?(-SEr-mJi?xQyA`YNCI#zG{m)v3 zH|PTx5rmf=FqoOlbA3^xkXH`diZ?We@hZn;zKFWS^nQgi4ZZax;1sLkrfI~Dm7F=p z46Vrcg7uSzUzc+`QpLLI>8Z#L-`L4rk+sgb`y4y`J8M7(y2(w1|8wFZkA-1kvu93R zk$AiH*T#PGz-n!Zl#7jVyf|p7xa{$7%s?B+rLt^Ql$JDsy>@9ZvkDngv@@u4|Zg@Ah6|TBWU&%$`GlW)Ygof6Y+mZ}h zsgf$KDbA)udj8y$)Vr<4xVJ>gM8f~e@Z5fm0&J4I%a@km8)yIODcH{Rue?X3RX34} zA+us5K&wk`@K4@^wP5}sv$Et~BaRDHUUffkFOelFR#Rw(7=HF~`FnqP>-ESOoB-y+ zlMlC^eE0F6zw^dtAODjLhhT9CZq7c>-1yE5}mlIo36%=S;3= zinaN|{fw6GjAT>GU8z}i;q*XHPfW2rP##QZq_#iHsFq5aD|u#n=2!}@hf%Eg64#ek zA|i{P$>ms3lrLM>4ck2nwJWzM`WYXVBq+(dy~?S#chKwr!hr-A)y(7cJFMt-#dhK* z3p}$|-)z6rv?%mR{!HdW;-gp%-00<%q$7OINQ&j~K?E5MZ26&A3COa1h+u*8li*WX z@dFi&xS7=NZ%L1V2Ff>_o4ihe-lKl%T3XWL8mglj^nR4g~^chW>aBU zIAnYCD>RiewKT6pLn`3XC3n7ju;B12gf|edG1-a+=TU84XpWX6I5{FFQ~A6d#QvYv zD9x~?6lYE+$ImN_sl%pqV&b}C8%DXd!j0f6nwLW-EeE8A08 z)W*^}&)Etuf0Gv~ HzxwpQFrD2M delta 2140 zcmZuxOK%%h6rMXCKVv&-;>3v`@gtAM3C*K*Qj(PPm82~NO530oQ%D`(o5YFjF?Ysk zV+uiS7Dy1a)m?Rglpq#GEQ$y$V1Zcl2OxHggjgX}>?*{D1>&6Rl7zOF{LQ)N`OP_J z?#*K#kNS0=&!fQa^Yo*9ICj?`A=mHrRVYy?q3%LcF^~yJ*;8mPwq#n0!Ay`SjBK{j zI_lk0Gi@v+Pd@73Qg4w=n5jz<_(y5|1_4iXvz^7ZNG8r)w1MuUjkIaQmPxS0Qc}1` zVk&UUmgzX9&^8)cS7?agxsxR}yJ&ce&!h&_mBwj8YWIV-hbCEv zD3Oj}s!f^KXo~i(+aaP?+WNqDpG4PEw1;V|=Fv|Fq(>iAd4Uc>l^&LwSLqNvxUNCu z0bp~8rh!dbvgwEOFdc#Oh&&HSc84MEMLH^Z41%VIj)7*J^+Tp3^d*^TNa`oHh?rFO zT}siTI~?b7SfqCOD_$x1f6DK zdI~+LdQtvUr^Q3{dnd8H)A<71zHR%BIJ#h*yi1t&GbAj2um=Hu3`E7B_No>GlPEaa zdM#~E*9*MnD*X|<5qbd9DD0Of@r@%lo&wQw8jP>xbL{CTnFK>EjqAEO4w9h(s2_T4 zd~o}M^L;`Nh@V`^rhd@Qq--41@m_>JVRxS;_2Rs{$t#O!ONL(JJ)-O$tJ`JQExvWX zN~VO((-jIpT*U?O`-ATuJ^1v@q-D=mXkO>h?Gv6swP6}eRku|2U(2pk#Z7M)iHiH) zSmPlueWCJ`@Zci|hs7`6gTV-j?P#-cDMzJ3Bz=pHQ546-9ben=Qz)JWu(Yynn7kg( zM-XbvO?KVnN6~I)oa>xB(e@HT7-3xe;p?86K(PZL<>pA0V==2v@|~SqHJQPWqeh$8 zd6Az$(IeB%%KVc1B*yLS4)qtwocP(FB$@5M{0-__20buywSFL5&JV2UFt`Dk;S8Fv z6Z~a_!w6>)UP0LD1wV(!*AdPmTmY!=(a^61IzH6(y+DhWt#U zLXB5RZu`B)GI7Wj42#E2iB4oMUq4m1^9qXPpsc`5_Jq0^3N#Jwl9dzGWQ%L{W$96TDd=*W4M&tx7RX4=1(Fhq8e@820maDuXnjdIV*6f>%3%5*m$M1XWnuo@?Lix nDeAORU=sx5jGF+O;94O&90O&3)We}#%7R`WFz(~;2BH;T#O=QJ3INCUJT=91jFSbtD3ZueNcVozb;*;iER=O!*V5&tqBhd9 z3%`n0f7hxl)m2?~5|NHU*i2*}mb{~4*VQ0uOhwZ>;DB*H&#aUoYiwsKmJvi=WHL|%sV;LtyDR_a!(DhiU&!1tL z6$Y6;VJKBae>eqiFdObjM$kz6_hwVSUlo6Z6Yw6xk>_w0yOA_SUfKp9a9lb76>Ldk zu!Z-f4t(64jZOp9upNuahJZ)eb@u;0rpkt>Q|LmG>}1YKDop^sU@w-Xk4wd6$l+Xk zM5?ji0?V}2RZS-i8z^Gi0#X7jV@rkkJ?S0Q4hv|=N)2Wf;V*lLp+yT)wAw4u_MXhd5? zP&_H(AP7Zju?Pi0qy^C;BAx^f^(MJ0SUmMmJbCa<0@_{Xd-J~eX5M=dL=y8nS!rqb$)=0Xy^wyp3?V0 z6R+#TVBtqS1K)64Uxx2%kCIt{GH!My%~tHnMw5|fGCwh6 z4Dbie7$)TLv9TvzCV@@rj%uY=XEQC=u9WMnN+E?>D;2oAj=zmG6fm9|fpNT)>T^;{ PSOK4>#-x5(_8$KWO6ZrX diff --git a/logs/server.log b/logs/server.log index 7847176431d4305318085c98439d5a07ae3cba31..43a164a8293ba63ac9bd5ddc4d7642d01b02756a 100644 GIT binary patch delta 154 zcmX@;a4dX+3ahb&p+)TE1M(^peJ8P47+aW6R$#P5W>}g*L`)0}Fc_vl5mOlpD`R6L zV-p2k1toXa5C#2`l4AXWqWrSVl+>b$AGKL5ObjewT44+$OQ4A2W>Y3Z+06k=-CUE? PWe$Zip%H#vuY!kJ%vY4A07*D>)WC>e%XkK_blNW=4}QFj+xqrOo=xhO(1i PYh7VCvM@C=jpYIWP9qs5 diff --git a/server.py b/server.py index ac5a0db..9865d4e 100644 --- a/server.py +++ b/server.py @@ -12,7 +12,7 @@ import aiohttp from fastapi import FastAPI, UploadFile, File, HTTPException, Form from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles -from fastapi.responses import FileResponse +from fastapi.responses import FileResponse, Response from pydantic import BaseModel # 导入 TTS 服务 @@ -255,6 +255,34 @@ async def synthesize_tts(text: str = Form(...), provider: Optional[str] = Form(N app.mount("/audio", StaticFiles(directory=AUDIO_DIR), name="audio") +# ChatTTS 音频代理(解决 HTTPS 页面访问 HTTP 资源问题) +@app.get("/chattts/audio/{filename}") +async def proxy_chattts_audio(filename: str): + """代理 ChatTTS 音频文件""" + import aiohttp + + chattts_url = os.getenv("CHATTTS_URL", "http://192.168.2.5:12002") + + try: + async with aiohttp.ClientSession() as session: + async with session.get( + f"{chattts_url}/audio/{filename}", + timeout=aiohttp.ClientTimeout(total=30) + ) as resp: + if resp.status != 200: + raise HTTPException(status_code=404, detail="Audio not found") + + audio_data = await resp.read() + return Response( + content=audio_data, + media_type="audio/wav", + headers={"Cache-Control": "public, max-age=3600"} + ) + except Exception as e: + logger.error(f"Proxy audio error: {e}") + raise HTTPException(status_code=500, detail=str(e)) + + if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=PORT) \ No newline at end of file diff --git a/tts_service.py b/tts_service.py index b104d1f..f333c88 100644 --- a/tts_service.py +++ b/tts_service.py @@ -134,8 +134,12 @@ class ChatTTSProvider(TTSProvider): raise Exception(f"ChatTTS error: {error}") data = await resp.json() - # ChatTTS 返回的 URL 是相对路径,需要拼接 - audio_url = f"{self.CHATTTS_URL}{data['audio_url']}" + # ChatTTS 返回的 URL 是 /audio/xxx.wav + # 改用本地代理路径(解决 HTTPS 页面访问 HTTP 问题) + original_url = data['audio_url'] + # /audio/xxx.wav -> /chattts/audio/xxx.wav (通过本地代理) + filename = original_url.split('/')[-1] + audio_url = f"/chattts/audio/{filename}" return None, audio_url def get_name(self) -> str: