OmniVoice_TTS_API / README.md
aspirant312's picture
Add clone-once voice registry (POST /voices + voice_id reuse)
912d5e5
|
Raw
History Blame Contribute Delete
5.4 kB
---
title: OmniVoice TTS
emoji: 🎙️
colorFrom: indigo
colorTo: green
sdk: docker
pinned: false
license: apache-2.0
short_description: In-process OmniVoice TTS Urdu / Punjabi / 600+ languages
suggested_hardware: t4-small
suggested_storage: small
---
# OmniVoice TTS — Self-hosted
Runs `k2-fsa/OmniVoice` directly on this Space's GPU (T4 / dedicated). No
upstream proxying — the model is loaded in-process at startup.
## Endpoints
| Method | Path | Purpose |
|--------|----------------|---------|
| GET | `/` | Service descriptor (JSON, lists languages / attributes) |
| GET | `/health` | Liveness probe |
| POST | `/tts` | One-shot WAV (audio/wav, 24 kHz mono int16) |
| POST | `/tts/stream` | Chunked WAV (header + raw PCM tail) — same JSON body |
| POST | `/tts/clone` | Ad-hoc voice cloning (multipart: `text`, `ref_audio`, `ref_text`?) |
| POST | `/voices` | Register a voice **once** (multipart: `name`, `ref_audio`, `ref_text`?) |
| GET | `/voices` | List cached voice ids |
| DELETE | `/voices/{name}` | Free a registered voice |
| WS | `/ws/tts` | Real-time PCM frames + JSON status messages |
## Request body (`/tts` and `/tts/stream`)
```json
{
"text": "آپ کا شکریہ",
"language": "Urdu",
"gender": "Female",
"age": "Young Adult",
"pitch": "Moderate",
"style": "Auto",
"accent": "Auto",
"dialect": "Auto",
"speed": 1.0,
"nfe_steps": 32,
"guidance": 2.0,
"denoise": true
}
```
- `language` accepts the English label (`"Urdu"`, `"Panjabi"`, `"Western Panjabi"`, …) or `"Auto"`.
- Voice-design attributes accept friendly aliases (`"female"`, `"young"`, `"low"`) **or** the canonical bilingual labels from the upstream Gradio demo (`"Female / 女"`, `"Young Adult / 青年"`).
- `instruct` (string) optionally overrides the auto-built attribute string with a free-form description.
## WebSocket protocol (`/ws/tts`)
```
client → server (text) : <TTSRequest JSON>
server → client (text) : {"type":"started","sample_rate":24000}
server → client (binary) : raw int16 PCM frames (~0.5 s each)
server → client (text) : {"type":"complete","duration_s":1.23}
```
On error: `{"type":"error","message":"..."}` then close.
## Voice cloning
Two modes:
### Ad-hoc (re-clones every request)
```bash
curl -X POST https://<space>.hf.space/tts/clone \
-F text="کلوننگ کا تجربہ" \
-F language=Urdu \
-F ref_audio=@reference.wav \
-F ref_text="ریفرنس آڈیو کا متن" \
--output cloned.wav
```
### Register once, reuse via `voice_id` (recommended)
Compute the clone prompt a single time, then synthesize unlimited utterances in
that voice without re-uploading or re-encoding the reference:
```bash
# 1. Register the voice ONCE (name it whatever you like)
curl -X POST https://<space>.hf.space/voices \
-F name=narrator_urdu \
-F ref_audio=@reference.wav \
-F ref_text="ریفرنس آڈیو کا متن"
# → {"voice_id":"narrator_urdu","voices_cached":1,"max_voices":50}
# 2. Reuse it on /tts, /tts/stream, or /ws/tts — just add "voice_id"
curl -X POST https://<space>.hf.space/tts \
-H 'Content-Type: application/json' \
-d '{"text":"آپ کا شکریہ","language":"Urdu","voice_id":"narrator_urdu"}' \
--output out.wav
curl https://<space>.hf.space/voices # list cached voices
curl -X DELETE https://<space>.hf.space/voices/narrator_urdu # free it
```
Notes:
- Re-registering the same `name` overwrites it (idempotent).
- An unknown `voice_id` returns **404** — register first.
- The cache is **in-process and in-memory**: voices are lost on restart/redeploy, and the least-recently-used voice is evicted once `OMNIVOICE_MAX_VOICES` (default 50) is exceeded.
- Omitting `ref_text` at registration triggers Whisper ASR, so it requires `OMNIVOICE_LOAD_ASR=1`.
## Configuration
Environment variables (set in the Space settings):
| Variable | Default | Purpose |
|---|---|---|
| `OMNIVOICE_MODEL` | `k2-fsa/OmniVoice` | HF repo id or local path |
| `OMNIVOICE_DEVICE` | `cuda` (auto-falls-back CPU) | torch device for the model |
| `OMNIVOICE_LOAD_ASR` | `1` | Set `0` to skip whisper download (saves ~1 GB) |
| `OMNIVOICE_MAX_VOICES`| `50` | Max registered voices kept in memory (LRU-evicted) |
| `LOG_LEVEL` | `INFO` | Python logging level |
| `PORT` | `7860` | HF Spaces standard port |
## Cold start
First request after a cold boot triggers the model download (~2 GB to `/data/.cache/huggingface`) and weight load (~30 s on T4). Subsequent requests are ~1–3 s/utterance for short Urdu / Punjabi sentences. The voice-agent client already retries 502/503/504 with backoff, so cold starts are absorbed silently.
## Pushing this Space
```bash
# From the repo root
huggingface-cli login
git -C deployments/omnivoice_space init
git -C deployments/omnivoice_space remote add origin https://huggingface.co/spaces/ebitlogix/omnivoice-tts
git -C deployments/omnivoice_space add .
git -C deployments/omnivoice_space commit -m "OmniVoice TTS — self-hosted FastAPI"
git -C deployments/omnivoice_space push -u origin main
```
After push, set hardware to `t4-small` (or higher) in the Space's "Settings → Hardware" tab.