endpoints: filter /v1/models and /v1/voices by engine availability flags
This commit is contained in:
parent
f25731ca08
commit
e9c978b051
1 changed files with 29 additions and 44 deletions
73
speech.py
73
speech.py
|
|
@ -66,6 +66,17 @@ except ImportError:
|
|||
torch = None
|
||||
F5TTS = None
|
||||
|
||||
def is_engine_available(model_id):
|
||||
"""Whether the TTS engine for a given model_id is loadable in this process.
|
||||
Used to filter advertised models/voices so we don't 503 on requests for
|
||||
engines whose Python deps weren't installed. tts-1/tts-1-hd/tts-1-silero/
|
||||
tts-1-kokoro are assumed available — they surface their own load errors."""
|
||||
if model_id == 'tts-1-qwen':
|
||||
return QWEN_TTS_AVAILABLE
|
||||
if model_id == 'tts-1-f5':
|
||||
return F5_TTS_AVAILABLE
|
||||
return True
|
||||
|
||||
@contextlib.asynccontextmanager
|
||||
async def lifespan(app):
|
||||
# Startup: Initialize voice caches in each worker process
|
||||
|
|
@ -74,10 +85,12 @@ async def lifespan(app):
|
|||
default_exists('config/pre_process_map.yaml')
|
||||
default_exists('config/voice_to_speaker.yaml')
|
||||
|
||||
# Build voice-to-model cache for fast lookups
|
||||
# Build voice-to-model cache for fast lookups (skip engines we can't load)
|
||||
with open('config/voice_to_speaker.yaml', 'r', encoding='utf8') as file:
|
||||
voice_map = yaml.safe_load(file)
|
||||
for model_id, voices in voice_map.items():
|
||||
if not is_engine_available(model_id):
|
||||
continue
|
||||
if isinstance(voices, dict):
|
||||
for voice_name in voices.keys():
|
||||
# First match wins (for duplicate voice names across models)
|
||||
|
|
@ -85,9 +98,11 @@ async def lifespan(app):
|
|||
voice_to_model_cache[voice_name] = model_id
|
||||
print(f"Voice-to-model cache initialized with {len(voice_to_model_cache)} voices")
|
||||
|
||||
# Build voices cache for /v1/voices endpoint
|
||||
# Build voices cache for /v1/voices endpoint (skip engines we can't load)
|
||||
models_data = []
|
||||
for model_id, voices in voice_map.items():
|
||||
if not is_engine_available(model_id):
|
||||
continue
|
||||
if isinstance(voices, dict):
|
||||
voice_list = list(voices.keys())
|
||||
|
||||
|
|
@ -731,51 +746,21 @@ def build_ffmpeg_args(response_format, input_format, sample_rate):
|
|||
|
||||
@app.get("/v1/models")
|
||||
async def list_models():
|
||||
"""List all available TTS models (OpenAI-compatible format)"""
|
||||
# Return minimal OpenAI-compatible model list (no extra fields)
|
||||
# tts-1-qwen and tts-1-f5 enabled by default
|
||||
return {
|
||||
"object": "list",
|
||||
"data": [
|
||||
{
|
||||
"id": "tts-1-qwen",
|
||||
"""List all available TTS models (OpenAI-compatible format).
|
||||
|
||||
Only advertise engines whose Python deps are actually loadable — otherwise
|
||||
clients try a model and get 503, which they treat as a transient outage.
|
||||
"""
|
||||
available = []
|
||||
for model_id in ('tts-1-qwen', 'tts-1-f5'):
|
||||
if is_engine_available(model_id):
|
||||
available.append({
|
||||
"id": model_id,
|
||||
"object": "model",
|
||||
"created": 1700000000,
|
||||
"owned_by": "uncloseai"
|
||||
},
|
||||
{
|
||||
"id": "tts-1-f5",
|
||||
"object": "model",
|
||||
"created": 1700000000,
|
||||
"owned_by": "uncloseai"
|
||||
}
|
||||
# Other models disabled by default:
|
||||
# {
|
||||
# "id": "tts-1",
|
||||
# "object": "model",
|
||||
# "created": 1700000000,
|
||||
# "owned_by": "uncloseai"
|
||||
# },
|
||||
# {
|
||||
# "id": "tts-1-hd",
|
||||
# "object": "model",
|
||||
# "created": 1700000000,
|
||||
# "owned_by": "uncloseai"
|
||||
# },
|
||||
# {
|
||||
# "id": "tts-1-silero",
|
||||
# "object": "model",
|
||||
# "created": 1700000000,
|
||||
# "owned_by": "uncloseai"
|
||||
# },
|
||||
# {
|
||||
# "id": "tts-1-kokoro",
|
||||
# "object": "model",
|
||||
# "created": 1700000000,
|
||||
# "owned_by": "uncloseai"
|
||||
# }
|
||||
]
|
||||
}
|
||||
})
|
||||
return {"object": "list", "data": available}
|
||||
|
||||
@app.get("/v1/voices")
|
||||
async def list_voices():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue