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)