perf: bound speech proxy synthesis
This commit is contained in:
parent
9517cca00c
commit
760a3640ba
@ -32,8 +32,9 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi
|
||||
- **Docker Socket Isolation.** Compose deployments now place the host Docker socket behind a dedicated network proxy;
|
||||
the web container no longer mounts the socket or joins the host Docker group. The client retains direct Unix-socket
|
||||
compatibility for deployments that intentionally configure it.
|
||||
- **TTS Queue Bound.** Preview, style-variation, and seed-finder synthesis now share a two-slot process-local queue;
|
||||
excess requests receive a retryable 429 after a bounded wait instead of creating unbounded worker threads.
|
||||
- **TTS Queue Bound.** Preview, style-variation, seed-finder, and OpenAI-compatible speech-proxy synthesis now share
|
||||
a two-slot process-local queue; excess requests receive a retryable 429 after a bounded wait instead of creating
|
||||
unbounded worker threads.
|
||||
- **STT Queue Bound.** Transcription and STT benchmark calls now share a single bounded process-local slot, preventing
|
||||
concurrent recognition requests from overcommitting the inference device.
|
||||
- **Visual Identity Versioning.** Consistent profile/reference results now carry the standardized v3 prompt marker,
|
||||
|
||||
4
TODO.md
4
TODO.md
@ -121,8 +121,8 @@ the first block before investing in architecture or polish.
|
||||
- [ ] Prevent duplicate generation when a user clicks twice.
|
||||
- [ ] Centralize provider health checks and error handling.
|
||||
- [ ] Limit concurrency to 1–2 image generations, 1–2 voice generations, and 1 STT request per user. Consistent
|
||||
portrait/reference rendering and preview/style/seed-finder synthesis are capped at two active jobs; extend the
|
||||
cap to full speech-proxy paths; STT transcription and benchmarks are capped at one active job.
|
||||
portrait/reference rendering, preview/style/seed-finder synthesis, and the OpenAI-compatible speech proxy are
|
||||
capped at two active jobs; STT transcription and benchmarks are capped at one active job.
|
||||
- [ ] Use bounded server queues.
|
||||
|
||||
## P0 — Security
|
||||
|
||||
@ -696,6 +696,8 @@ async def tts_preview(request: Request):
|
||||
)
|
||||
else:
|
||||
audio, media_type = await _bounded_tts_call(_preview_request_audio, text, voice, settings, instruct, backend)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(502, f"TTS error: {e}")
|
||||
audio, media_type, ext, duration_sec, clipped = _prepare_proxy_audio(audio, media_type, response_format)
|
||||
@ -733,6 +735,8 @@ async def tts_style_variation(request: Request):
|
||||
try:
|
||||
audio, media_type = await _bounded_tts_call(_preview_request_audio, text, source_voice, settings, instruct, backend)
|
||||
audio, media_type, _ext, duration, _clipped = _prepare_proxy_audio(audio, media_type, "wav")
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(502, f"Style variation synthesis failed: {e}")
|
||||
|
||||
@ -959,7 +963,9 @@ async def openai_speech_proxy(request: Request):
|
||||
|
||||
if backend == "streaming" and not virtual and response_format == "wav" and not route_has_sounds and not route_has_speed:
|
||||
try:
|
||||
resp = await asyncio.to_thread(_open_tts_stream_response, text, voice, settings, style_instruction)
|
||||
resp = await _bounded_tts_call(_open_tts_stream_response, text, voice, settings, style_instruction)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
_routing_log_request(
|
||||
request, status="error", app=request_app, requested_voice=original_voice,
|
||||
@ -996,43 +1002,45 @@ async def openai_speech_proxy(request: Request):
|
||||
instruct = str(preset.get("description", "")).strip()
|
||||
if not instruct:
|
||||
raise RuntimeError(f"Virtual voice '{voice}' has no description")
|
||||
audio, media_type = await asyncio.to_thread(
|
||||
audio, media_type = await _bounded_tts_call(
|
||||
_voice_design_request_audio,
|
||||
instruct, text, str(preset.get("language", "Auto")), settings,
|
||||
str(preset.get("gender", "")),
|
||||
)
|
||||
elif backend == "voice_design":
|
||||
audio, media_type = await asyncio.to_thread(
|
||||
audio, media_type = await _bounded_tts_call(
|
||||
_voice_design_voice_request_audio,
|
||||
voice, text, settings, style_instruction, str(data.get("language") or "Auto"),
|
||||
)
|
||||
elif backend == "streaming":
|
||||
resp = await asyncio.to_thread(_open_tts_stream_response, text, voice, settings, style_instruction)
|
||||
audio, media_type = await asyncio.to_thread(_read_tts_stream_response, resp)
|
||||
resp = await _bounded_tts_call(_open_tts_stream_response, text, voice, settings, style_instruction)
|
||||
audio, media_type = await _bounded_tts_call(_read_tts_stream_response, resp)
|
||||
if not audio:
|
||||
raise RuntimeError("backend returned empty audio")
|
||||
elif backend == "nvidia_magpie":
|
||||
audio, media_type = await asyncio.to_thread(
|
||||
audio, media_type = await _bounded_tts_call(
|
||||
_tts_request_audio, text, voice, settings, style_instruction,
|
||||
_preview_backend_base_url(settings, "nvidia_magpie"),
|
||||
settings.get("tts_api_key", ""), "nvidia_magpie", "nvidia_magpie",
|
||||
)
|
||||
elif backend in {"nvidia_zeroshot", "nvidia_flow"}:
|
||||
audio, media_type = await asyncio.to_thread(
|
||||
audio, media_type = await _bounded_tts_call(
|
||||
_nvidia_clone_request_audio, text, voice, settings,
|
||||
"flow" if backend == "nvidia_flow" else "zeroshot",
|
||||
str(data.get("audio_prompt_transcript") or ""),
|
||||
str(data.get("language") or ""),
|
||||
)
|
||||
elif backend == "fishspeech":
|
||||
audio, media_type = await asyncio.to_thread(
|
||||
audio, media_type = await _bounded_tts_call(
|
||||
_fishspeech_request_audio, text, voice, settings,
|
||||
style_instruction, str(data.get("language") or ""),
|
||||
)
|
||||
else:
|
||||
audio, media_type = await asyncio.to_thread(
|
||||
audio, media_type = await _bounded_tts_call(
|
||||
_tts_request_audio, text, voice, settings, style_instruction,
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
_routing_log_request(
|
||||
request, status="error", app=request_app, requested_voice=original_voice,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user