Skip to content

Add speech-to-text and text-to-speech endpoints - #428

Merged
Priyanshu-u07 merged 4 commits into
InferiaAI:mainfrom
Dhirenderchoudhary:feat/audio-endpoints
Oct 24, 2026
Merged

Priyanshu-u07 merged 4 commits into
InferiaAI:mainfrom
Dhirenderchoudhary:feat/audio-endpoints

Conversation

@Dhirenderchoudhary

Copy link
Copy Markdown
Collaborator

ModelType.AUDIO_GENERATION already lists /v1/audio/speech and /v1/audio/transcriptions, but the inference service didn't serve them, so speech models couldn't be used through InferiaLLM. This adds both, OpenAI-compatible, so a speech-to-text or text-to-speech deployment works with an API key (or the sandbox header) like a chat model.

  • POST /v1/audio/transcriptions: multipart file + model (other form fields like language pass through). Returns the upstream JSON, e.g. {"text": "..."}.
  • POST /v1/audio/speech: JSON {model, input, voice, ...}. Returns the audio bytes with the upstream content type.
  • Both resolve deployments with model_type = audio_generation and go through the same rate limit, quota, usage log and circuit breaker as the other routes.
  • New engine name speaches (speaches, an OpenAI-compatible server for faster-whisper and Kokoro/Piper). Any OpenAI-compatible engine works too, since the paths are on the base adapter.
  • GatewayService.call_upstream_raw for these two, because call_upstream only does JSON in/JSON out. It reuses the same URL validation, header sanitizing, concurrency limit, size cap and breaker.
  • The REST deployments list now returns model_type. It was already in the gRPC Deployment message but got dropped, so the dashboard couldn't tell an STT model from an LLM.

Testing:

  • src/tests/inference/test_audio_endpoints.py: calls the real routes with an httpx.MockTransport upstream. It checks the multipart body reaches upstream with the deployment's inference_model, audio bytes and content type come back, missing fields are a 400, and upstream 4xx is passed through.
  • test_listing_includes_model_type for the list change.
  • Ran it locally in docker with speaches (faster-whisper-tiny.en, Kokoro-82M) registered as external deployments, through /inf/v1 with an API key: TTS returned a 24 kHz WAV in 2.7s, and sending that WAV to STT came back as the exact sentence. A browser webm/opus recording also transcribes correctly.
  • Full suite with the CI ignore list: same failures as main.

The API key is only validated after the form is read, so uploads are now size-checked first (25 MB). TTS is slow, so input is capped at 4096 characters to stop long texts blocking the speech server. Upstream content types are limited to audio, JSON and text, with nosniff, since /inf shares the dashboard's origin.

Signed-off-by: Priyanshu-u07 <connect.priyanshu8271@gmail.com>
@Priyanshu-u07

Copy link
Copy Markdown
Collaborator

Reviewed this and pushed a fix commit (fbd39a0) for three issues:

  • Upload size: the transcription endpoint read the whole file into memory before the API key was checked, with no size limit, so a fake key plus a huge file could exhaust the inference service's memory. Uploads over 25 MB are now refused before reading.
  • TTS input: no limit on input length; now capped at 4,096 characters (same as OpenAI), since TTS is slow and long texts block the speech server.
  • Content types: the upstream's content type was passed straight through, and /inf shares the dashboard's origin. Only audio, JSON and text types are passed now, with nosniff.

Added 3 tests; they fail without the fix. Full suite shows the same failures as main.

Note for the canvas (#429): an LLM answer over 4,096 characters would now get a 400 from TTS, though voice replies are far below that.

Follow-ups, not blocking: audio requests don't count toward the token quota yet and behind nginx the default 1 MB body limit will reject real recordings.

@Priyanshu-u07
Priyanshu-u07 merged commit cc37575 into InferiaAI:main Oct 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants