File size: 1,820 Bytes
e4ba58b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
import io
import base64
import torch
import soundfile as sf
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from transformers import AutoModel, AutoTokenizer

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

MODEL_ID = "ai4bharat/vits_rasa_13"
HF_TOKEN = os.environ.get("HF_TOKEN")

# Preload model weights into memory
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=True, token=HF_TOKEN)
model = AutoModel.from_pretrained(MODEL_ID, trust_remote_code=True, token=HF_TOKEN)
model.eval()

class TTSRequest(BaseModel):
    text: str
    gender: str = "male"  # male = 5 (BRX_M), female = 4 (BRX_F)

@app.get("/")
def health():
    return {"status": "running", "engine": "ai4bharat-bodo-vits"}

@app.post("/synthesize")
def synthesize(req: TTSRequest):
    text = req.text.strip()
    if not text:
        raise HTTPException(status_code=400, detail="Text cannot be empty.")

    # Speaker mapping: 5 = Bodo Male, 4 = Bodo Female
    # Style mapping: 4 = Conversational (CONV)
    speaker_id = 5 if req.gender == "male" else 4
    style_id = 4

    try:
        inputs = tokenizer(text=text, return_tensors="pt")
        with torch.no_grad():
            outputs = model(inputs["input_ids"], speaker_id=speaker_id, emotion_id=style_id)

        buffer = io.BytesIO()
        sf.write(buffer, outputs.waveform.squeeze().cpu().numpy(), model.config.sampling_rate, format="WAV")
        b64_audio = base64.b64encode(buffer.getvalue()).decode("utf-8")

        return {"audioUrl": f"data:audio/wav;base64,{b64_audio}"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))