File size: 2,183 Bytes
a783ac1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | import uvicorn
from fastapi import FastAPI, HTTPException
from fastapi.responses import FileResponse
from pydantic import BaseModel
import ChatTTS
import scipy.io.wavfile as wavfile
import numpy as np
import os
app = FastAPI(title="Local ChatTTS Server (Fixed Index)")
print("正在載入 ChatTTS 模型...")
chat = ChatTTS.Chat()
chat.load()
print("模型載入完成!")
class TTSRequest(BaseModel):
text: str
@app.post("/v1/audio/speech")
async def text_to_speech(request: TTSRequest):
script_dir = os.path.dirname(os.path.abspath(__file__))
record_dir = os.path.join(script_dir, "../record")
os.makedirs(record_dir, exist_ok=True)
output_path = os.path.join(record_dir, "output.wav")
try:
# 1. 進行推理 (使用 InferCodeParams 對象,限制最大 token 數,避免無限生成)
params_infer_code = ChatTTS.Chat.InferCodeParams(
max_new_token=384
)
res = chat.infer(
[request.text],
use_decoder=True,
params_infer_code=params_infer_code
)
# 2. 智慧型格式剝離:確保拿到最裡面的純音訊數據
if isinstance(res, list):
audio_data = res[0]
else:
audio_data = res
if isinstance(audio_data, list) or (hasinstance := hasattr(audio_data, 'ndim') and audio_data.ndim > 1):
if hasattr(audio_data, 'ndim') and audio_data.ndim > 1:
audio_data = audio_data[0]
else:
audio_data = audio_data[0]
# 3. 強制轉換成標準 1D float32 numpy 陣列並拉平
audio_data = np.array(audio_data, dtype=np.float32).flatten()
# 4. 寫入 WAV 檔案
wavfile.write(output_path, 24000, audio_data)
if os.path.exists(output_path):
return FileResponse(output_path, media_type="audio/wav", filename="speech.wav")
else:
raise HTTPException(status_code=500, detail="語音檔案生成失敗")
except Exception as e:
raise HTTPException(status_code=500, detail=f"TTS 處理失敗: {str(e)}")
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=4003)
|