Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -9,7 +9,7 @@ from typing import Optional
|
|
| 9 |
|
| 10 |
import requests
|
| 11 |
import torch
|
| 12 |
-
from fastapi import Body, FastAPI, Header, HTTPException
|
| 13 |
from fastapi.responses import FileResponse, JSONResponse
|
| 14 |
from pydantic import BaseModel, Field, HttpUrl
|
| 15 |
|
|
@@ -104,9 +104,20 @@ def health(x_api_key: Optional[str] = Header(default=None)):
|
|
| 104 |
return {"status": "ok", "model": "xtts_v2", "device": DEVICE}
|
| 105 |
|
| 106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
@app.post("/generate")
|
| 108 |
def generate(
|
| 109 |
payload: GenerateRequest = Body(...),
|
|
|
|
| 110 |
x_api_key: Optional[str] = Header(default=None),
|
| 111 |
):
|
| 112 |
_require_api_key(x_api_key)
|
|
@@ -126,19 +137,29 @@ def generate(
|
|
| 126 |
split_sentences=True,
|
| 127 |
)
|
| 128 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
return FileResponse(output_file, media_type="audio/wav", filename="output.wav")
|
| 130 |
|
| 131 |
except HTTPException:
|
|
|
|
|
|
|
|
|
|
| 132 |
raise
|
| 133 |
except Exception as exc: # pragma: no cover
|
| 134 |
-
|
| 135 |
-
finally:
|
| 136 |
if speaker_file and Path(speaker_file).exists():
|
| 137 |
Path(speaker_file).unlink(missing_ok=True)
|
| 138 |
if output_file and Path(output_file).exists():
|
| 139 |
Path(output_file).unlink(missing_ok=True)
|
|
|
|
| 140 |
|
| 141 |
|
| 142 |
@app.get("/")
|
| 143 |
def root():
|
| 144 |
-
return {"name": "xtts-v2-api", "endpoints": ["/health", "/generate"]}
|
|
|
|
| 9 |
|
| 10 |
import requests
|
| 11 |
import torch
|
| 12 |
+
from fastapi import BackgroundTasks, Body, FastAPI, Header, HTTPException
|
| 13 |
from fastapi.responses import FileResponse, JSONResponse
|
| 14 |
from pydantic import BaseModel, Field, HttpUrl
|
| 15 |
|
|
|
|
| 104 |
return {"status": "ok", "model": "xtts_v2", "device": DEVICE}
|
| 105 |
|
| 106 |
|
| 107 |
+
def _cleanup_files(*files: str):
|
| 108 |
+
"""Background task to clean up temporary files after response is sent."""
|
| 109 |
+
for file_path in files:
|
| 110 |
+
if file_path and Path(file_path).exists():
|
| 111 |
+
try:
|
| 112 |
+
Path(file_path).unlink(missing_ok=True)
|
| 113 |
+
except Exception:
|
| 114 |
+
pass # Ignore cleanup errors
|
| 115 |
+
|
| 116 |
+
|
| 117 |
@app.post("/generate")
|
| 118 |
def generate(
|
| 119 |
payload: GenerateRequest = Body(...),
|
| 120 |
+
background_tasks: BackgroundTasks = BackgroundTasks(),
|
| 121 |
x_api_key: Optional[str] = Header(default=None),
|
| 122 |
):
|
| 123 |
_require_api_key(x_api_key)
|
|
|
|
| 137 |
split_sentences=True,
|
| 138 |
)
|
| 139 |
|
| 140 |
+
# Verify the output file was created
|
| 141 |
+
if not Path(output_file).exists():
|
| 142 |
+
raise RuntimeError(f"TTS generation failed: output file was not created at {output_file}")
|
| 143 |
+
|
| 144 |
+
# Schedule cleanup after response is sent
|
| 145 |
+
background_tasks.add_task(_cleanup_files, speaker_file, output_file)
|
| 146 |
+
|
| 147 |
return FileResponse(output_file, media_type="audio/wav", filename="output.wav")
|
| 148 |
|
| 149 |
except HTTPException:
|
| 150 |
+
# Clean up on HTTPException
|
| 151 |
+
if speaker_file and Path(speaker_file).exists():
|
| 152 |
+
Path(speaker_file).unlink(missing_ok=True)
|
| 153 |
raise
|
| 154 |
except Exception as exc: # pragma: no cover
|
| 155 |
+
# Clean up on error
|
|
|
|
| 156 |
if speaker_file and Path(speaker_file).exists():
|
| 157 |
Path(speaker_file).unlink(missing_ok=True)
|
| 158 |
if output_file and Path(output_file).exists():
|
| 159 |
Path(output_file).unlink(missing_ok=True)
|
| 160 |
+
return JSONResponse(status_code=500, content={"error": str(exc)})
|
| 161 |
|
| 162 |
|
| 163 |
@app.get("/")
|
| 164 |
def root():
|
| 165 |
+
return {"name": "xtts-v2-api", "endpoints": ["/health", "/generate"]}
|