Spaces:
Runtime error
Runtime error
| # βββ ENV SETUP (VERY IMPORTANT - keep at top) ββββββββββββββββββββββββββββββββ | |
| import os | |
| os.environ["COQUI_TOS_AGREED"] = "1" | |
| # βββ IMPORTS ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| from fastapi import FastAPI | |
| from fastapi.responses import FileResponse, JSONResponse | |
| from pydantic import BaseModel | |
| from TTS.api import TTS | |
| import uuid | |
| import threading | |
| import time | |
| # βββ APP INIT βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| app = FastAPI() | |
| # βββ LOAD MODEL (runs once) βββββββββββββββββββββββββββββββββββββββββββββββββ | |
| tts = TTS( | |
| model_name="tts_models/multilingual/multi-dataset/xtts_v2", | |
| progress_bar=False, | |
| gpu=False | |
| ) | |
| # βββ REQUEST MODEL ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class TTSRequest(BaseModel): | |
| text: str | |
| # βββ CLEANUP FUNCTION βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def cleanup_file(path: str): | |
| time.sleep(15) # wait before deleting | |
| try: | |
| if os.path.exists(path): | |
| os.remove(path) | |
| except Exception as e: | |
| print(f"Cleanup error: {e}") | |
| # βββ ROUTE ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async def generate_audio(req: TTSRequest): | |
| try: | |
| # Validate input | |
| if not req.text or not req.text.strip(): | |
| return JSONResponse( | |
| status_code=400, | |
| content={"error": "Text input is empty"} | |
| ) | |
| # Check speaker file exists | |
| speaker_path = "sage.wav" | |
| if not os.path.exists(speaker_path): | |
| return JSONResponse( | |
| status_code=500, | |
| content={"error": "Speaker file (sage.wav) missing on server"} | |
| ) | |
| # Generate unique output file | |
| file_name = f"output_{uuid.uuid4().hex}.wav" | |
| # Generate speech | |
| tts.tts_to_file( | |
| text=req.text, | |
| speaker_wav=speaker_path, | |
| file_path=file_name | |
| ) | |
| # Schedule cleanup | |
| threading.Thread(target=cleanup_file, args=(file_name,)).start() | |
| # Return audio file | |
| return FileResponse( | |
| file_name, | |
| media_type="audio/wav", | |
| filename="speech.wav" | |
| ) | |
| except Exception as e: | |
| print(f"TTS ERROR: {e}") | |
| return JSONResponse( | |
| status_code=500, | |
| content={"error": str(e)} | |
| ) |