ivan.lee
Initial commit with LFS tracking
a783ac1
Raw
History Blame Contribute Delete
2.18 kB
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)