ChandimaPrabath's picture
Create app.py
c620425 verified
from fastapi import FastAPI, HTTPException, Response
from pydantic import BaseModel
import requests
import base64
import os
app = FastAPI(title="OpenAI‑Compatible TTS Adapter")
class OpenAITTSRequest(BaseModel):
model: str # e.g. "tts-1"
input: str # the text prompt
voice: str = "tara" # optional voice parameter
format: str = "wav" # "wav" or "mp3"
@app.post(
"/v1/audio/speech",
summary="Generate speech",
response_class=Response, # raw bytes
)
def tts_speech(req: OpenAITTSRequest):
# Load your Chutes token
chutes_token = os.getenv("CHUTES_API_TOKEN")
if not chutes_token:
raise HTTPException(status_code=500, detail="Chutes API token not configured")
# Call Chutes TTS
resp = requests.post(
"https://chutes-orpheus-tts.chutes.ai/speak",
headers={
"Authorization": f"Bearer {chutes_token}",
"Content-Type": "application/json"
},
json={"voice": req.voice, "prompt": req.input},
timeout=30
)
if resp.status_code != 200:
raise HTTPException(
status_code=502,
detail=f"Chutes TTS error: {resp.status_code} {resp.text}"
)
# If Chutes returns JSON-wrapped base64, extract and decode
content_type = f"audio/{req.format}"
try:
segments = resp.json()
for seg in segments:
if seg.get("type") == "audio" and seg.get("data"):
# data:audio/wav;base64,AAAA...
prefix, b64 = seg["data"].split(",", 1)
audio_bytes = base64.b64decode(b64)
return Response(content=audio_bytes, media_type=content_type)
except ValueError:
# Not JSON — assume raw bytes
return Response(content=resp.content, media_type=content_type)
raise HTTPException(status_code=502, detail="No audio in Chutes response")
@app.get("/healthz")
def health_check():
return {"status": "ok"}