Spaces:
Running
Running
Commit
·
9f83ce7
1
Parent(s):
8f5ae34
fixes.
Browse files- .gitattributes +0 -35
- Dockerfile +0 -2
- README.md +12 -4
- app.py +5 -10
- requirements.txt +4 -2
- spaces.yaml +0 -1
.gitattributes
DELETED
|
@@ -1,35 +0,0 @@
|
|
| 1 |
-
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Dockerfile
CHANGED
|
@@ -16,7 +16,5 @@ RUN pip install --upgrade pip && pip install -r requirements.txt
|
|
| 16 |
|
| 17 |
COPY app.py ./
|
| 18 |
|
| 19 |
-
# Default port for Spaces
|
| 20 |
ENV PORT=7860
|
| 21 |
-
|
| 22 |
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
|
|
|
| 16 |
|
| 17 |
COPY app.py ./
|
| 18 |
|
|
|
|
| 19 |
ENV PORT=7860
|
|
|
|
| 20 |
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
---
|
| 2 |
title: xtts-v2-api
|
| 3 |
-
emoji: 🗣️
|
| 4 |
colorFrom: purple
|
| 5 |
colorTo: blue
|
| 6 |
sdk: docker
|
|
@@ -20,11 +20,16 @@ FastAPI service exposing XTTS v2 for text-to-speech and voice cloning.
|
|
| 20 |
Send header `x-api-key: $SPACE_API_KEY` (set this secret in Space settings).
|
| 21 |
|
| 22 |
## Request body (`/generate`)
|
|
|
|
| 23 |
{
|
| 24 |
"text": "Hello from XTTS",
|
| 25 |
"speaker_wav": "https://.../sample.wav or base64 string",
|
| 26 |
"language": "en"
|
| 27 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
curl -X POST https://<space>.hf.space/health \
|
| 29 |
-H "x-api-key: $SPACE_API_KEY"
|
| 30 |
|
|
@@ -32,6 +37,9 @@ curl -X POST https://<space>.hf.space/generate \
|
|
| 32 |
-H "Content-Type: application/json" \
|
| 33 |
-H "x-api-key: $SPACE_API_KEY" \
|
| 34 |
-d '{"text":"Hello from XTTS","speaker_wav":"https://.../sample.wav"}' \
|
| 35 |
-
--output out.wav
|
|
|
|
|
|
|
|
|
|
| 36 |
- Hardware: request T4 GPU for best latency (CPU works but slower).
|
| 37 |
-
- Env vars for clients: `HF_SPACES_API_URL`, `HF_SPACES_API_KEY`.
|
|
|
|
| 1 |
---
|
| 2 |
title: xtts-v2-api
|
| 3 |
+
emoji: "🗣️"
|
| 4 |
colorFrom: purple
|
| 5 |
colorTo: blue
|
| 6 |
sdk: docker
|
|
|
|
| 20 |
Send header `x-api-key: $SPACE_API_KEY` (set this secret in Space settings).
|
| 21 |
|
| 22 |
## Request body (`/generate`)
|
| 23 |
+
```json
|
| 24 |
{
|
| 25 |
"text": "Hello from XTTS",
|
| 26 |
"speaker_wav": "https://.../sample.wav or base64 string",
|
| 27 |
"language": "en"
|
| 28 |
+
}
|
| 29 |
+
```
|
| 30 |
+
|
| 31 |
+
## Smoke tests
|
| 32 |
+
```bash
|
| 33 |
curl -X POST https://<space>.hf.space/health \
|
| 34 |
-H "x-api-key: $SPACE_API_KEY"
|
| 35 |
|
|
|
|
| 37 |
-H "Content-Type: application/json" \
|
| 38 |
-H "x-api-key: $SPACE_API_KEY" \
|
| 39 |
-d '{"text":"Hello from XTTS","speaker_wav":"https://.../sample.wav"}' \
|
| 40 |
+
--output out.wav
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
## Notes
|
| 44 |
- Hardware: request T4 GPU for best latency (CPU works but slower).
|
| 45 |
+
- Env vars for clients: `HF_SPACES_API_URL`, `HF_SPACES_API_KEY`.
|
app.py
CHANGED
|
@@ -16,15 +16,11 @@ SPACE_API_KEY = os.getenv("SPACE_API_KEY")
|
|
| 16 |
MAX_TEXT_LENGTH = 1000
|
| 17 |
DEFAULT_LANGUAGE = "en"
|
| 18 |
|
| 19 |
-
# Pick CUDA if available
|
| 20 |
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
| 21 |
|
| 22 |
-
# Load the XTTS v2 model once at startup
|
| 23 |
-
# Hugging Face Spaces caches model weights on persistent storage
|
| 24 |
try:
|
| 25 |
tts_model = TTS("tts_models/multilingual/multi-dataset/xtts_v2", gpu=DEVICE == "cuda")
|
| 26 |
-
except Exception as exc: # pragma: no cover
|
| 27 |
-
# Fail fast on startup; Spaces will show the error in logs
|
| 28 |
raise RuntimeError(f"Failed to load XTTS v2 model: {exc}") from exc
|
| 29 |
|
| 30 |
app = FastAPI(title="xtts-v2-api", version="1.0.0")
|
|
@@ -32,8 +28,8 @@ app = FastAPI(title="xtts-v2-api", version="1.0.0")
|
|
| 32 |
|
| 33 |
class GenerateRequest(BaseModel):
|
| 34 |
text: str = Field(..., min_length=1, max_length=MAX_TEXT_LENGTH)
|
| 35 |
-
speaker_wav: str = Field(..., description="HTTPS URL or base64-encoded
|
| 36 |
-
language: Optional[str] = Field(DEFAULT_LANGUAGE, description="ISO
|
| 37 |
|
| 38 |
|
| 39 |
def _require_api_key(x_api_key: Optional[str]):
|
|
@@ -58,7 +54,7 @@ def _write_temp_audio_from_url(url: HttpUrl) -> str:
|
|
| 58 |
def _write_temp_audio_from_base64(payload: str) -> str:
|
| 59 |
try:
|
| 60 |
raw = base64.b64decode(payload)
|
| 61 |
-
except Exception as exc: # pragma: no cover
|
| 62 |
raise HTTPException(status_code=400, detail="Invalid base64 speaker_wav") from exc
|
| 63 |
with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp:
|
| 64 |
tmp.write(raw)
|
|
@@ -104,8 +100,7 @@ def generate(
|
|
| 104 |
|
| 105 |
except HTTPException:
|
| 106 |
raise
|
| 107 |
-
except Exception as exc: # pragma: no cover
|
| 108 |
-
# Surface readable errors to client
|
| 109 |
return JSONResponse(status_code=500, content={"error": str(exc)})
|
| 110 |
finally:
|
| 111 |
if speaker_file and Path(speaker_file).exists():
|
|
|
|
| 16 |
MAX_TEXT_LENGTH = 1000
|
| 17 |
DEFAULT_LANGUAGE = "en"
|
| 18 |
|
|
|
|
| 19 |
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
| 20 |
|
|
|
|
|
|
|
| 21 |
try:
|
| 22 |
tts_model = TTS("tts_models/multilingual/multi-dataset/xtts_v2", gpu=DEVICE == "cuda")
|
| 23 |
+
except Exception as exc: # pragma: no cover
|
|
|
|
| 24 |
raise RuntimeError(f"Failed to load XTTS v2 model: {exc}") from exc
|
| 25 |
|
| 26 |
app = FastAPI(title="xtts-v2-api", version="1.0.0")
|
|
|
|
| 28 |
|
| 29 |
class GenerateRequest(BaseModel):
|
| 30 |
text: str = Field(..., min_length=1, max_length=MAX_TEXT_LENGTH)
|
| 31 |
+
speaker_wav: str = Field(..., description="HTTPS URL or base64-encoded audio")
|
| 32 |
+
language: Optional[str] = Field(DEFAULT_LANGUAGE, description="ISO code, default en")
|
| 33 |
|
| 34 |
|
| 35 |
def _require_api_key(x_api_key: Optional[str]):
|
|
|
|
| 54 |
def _write_temp_audio_from_base64(payload: str) -> str:
|
| 55 |
try:
|
| 56 |
raw = base64.b64decode(payload)
|
| 57 |
+
except Exception as exc: # pragma: no cover
|
| 58 |
raise HTTPException(status_code=400, detail="Invalid base64 speaker_wav") from exc
|
| 59 |
with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp:
|
| 60 |
tmp.write(raw)
|
|
|
|
| 100 |
|
| 101 |
except HTTPException:
|
| 102 |
raise
|
| 103 |
+
except Exception as exc: # pragma: no cover
|
|
|
|
| 104 |
return JSONResponse(status_code=500, content={"error": str(exc)})
|
| 105 |
finally:
|
| 106 |
if speaker_file and Path(speaker_file).exists():
|
requirements.txt
CHANGED
|
@@ -1,8 +1,10 @@
|
|
| 1 |
TTS==0.22.0
|
| 2 |
fastapi==0.104.1
|
| 3 |
uvicorn==0.24.0
|
| 4 |
-
torch==2.1.0
|
| 5 |
-
torchaudio==2.1.0
|
| 6 |
python-multipart==0.0.6
|
| 7 |
requests==2.31.0
|
| 8 |
numpy==1.26.4
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
TTS==0.22.0
|
| 2 |
fastapi==0.104.1
|
| 3 |
uvicorn==0.24.0
|
|
|
|
|
|
|
| 4 |
python-multipart==0.0.6
|
| 5 |
requests==2.31.0
|
| 6 |
numpy==1.26.4
|
| 7 |
+
|
| 8 |
+
# Use CPU wheels by default; HF GPU image will still use CUDA when available.
|
| 9 |
+
torch==2.1.0 --index-url https://download.pytorch.org/whl/cpu
|
| 10 |
+
torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cpu
|
spaces.yaml
CHANGED
|
@@ -1,5 +1,4 @@
|
|
| 1 |
title: xtts-v2-api
|
| 2 |
sdk: docker
|
| 3 |
-
dockerfile: Dockerfile
|
| 4 |
python_version: 3.10
|
| 5 |
app_file: app.py
|
|
|
|
| 1 |
title: xtts-v2-api
|
| 2 |
sdk: docker
|
|
|
|
| 3 |
python_version: 3.10
|
| 4 |
app_file: app.py
|