Add /v1/models endpoint for voice discovery

- Implemented GET /v1/models endpoint
- Returns list of all TTS models with metadata
- Includes voice lists for each model
- Provides engine-specific information (sample rate, description)
- Enables frontend voice discovery and model type mapping

Response format:
{
  "object": "list",
  "data": [
    {
      "id": "tts-1",
      "engine": "piper",
      "description": "Fast neural TTS with 100+ voices",
      "sample_rate": 22050,
      "voices": [...],
      "voice_count": 40
    },
    ...
  ]
}

🦝 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Russell Ballestrini 2025-11-09 13:39:32 -05:00
parent d48fa6b29c
commit 603a211f47

View file

@ -286,6 +286,55 @@ def build_ffmpeg_args(response_format, input_format, sample_rate):
return ffmpeg_args
@app.get("/v1/models")
async def list_models():
"""List all available TTS models and their supported voices"""
default_exists('config/voice_to_speaker.yaml')
with open('config/voice_to_speaker.yaml', 'r', encoding='utf8') as file:
voice_map = yaml.safe_load(file)
models_data = []
for model_id, voices in voice_map.items():
if isinstance(voices, dict):
voice_list = list(voices.keys())
# Add model metadata
model_info = {
"id": model_id,
"object": "model",
"created": 1700000000, # Static timestamp
"owned_by": "uncloseai",
"voices": voice_list,
"voice_count": len(voice_list)
}
# Add engine-specific metadata
if model_id == 'tts-1':
model_info["engine"] = "piper"
model_info["description"] = "Fast neural TTS with 100+ voices"
model_info["sample_rate"] = 22050
elif model_id == 'tts-1-hd':
model_info["engine"] = "xtts"
model_info["description"] = "High-quality voice cloning TTS"
model_info["sample_rate"] = 24000
elif model_id == 'tts-1-silero':
model_info["engine"] = "silero"
model_info["description"] = "Fast multilingual TTS (en, ru, de, es, fr)"
model_info["sample_rate"] = 48000
elif model_id == 'tts-1-kokoro':
model_info["engine"] = "kokoro"
model_info["description"] = "Lightweight decoder-only TTS (82M params)"
model_info["sample_rate"] = 24000
models_data.append(model_info)
return {
"object": "list",
"data": models_data
}
@app.post("/v1/audio/speech", response_class=StreamingResponse)
async def generate_speech(request: GenerateSpeechRequest):
global xtts, args