Advanced API¶
Who this is for: developers integrating with the speech service.
The speech service (caption-local) exposes a small HTTP API. It is built for a
local, trusted producer: by default there is no CORS allowance, no multi-tenant
isolation and no permanent store. This page is a concise reference; the upstream
API.md carries the full contract.
When CAPTION_API_KEY is set, every actual API request must carry the service
access token as a Bearer header. Preflight OPTIONS requests do not require it.
Service access token
Send Authorization: Bearer <token>, where <token> is the configured
CAPTION_API_KEY. See
Concepts in plain words.
Endpoints at a glance¶
| Method | Path | What it does |
|---|---|---|
GET |
/v1/models |
Returns the one loaded local model. |
POST |
/v1/audio/transcriptions |
OpenAI-style transcription of an uploaded WAV. |
POST |
/v1/audio/translations |
OpenAI-style speech-to-English translation. |
POST |
/transcribe |
Native PCM endpoint for rolling live capture. |
GET |
/health |
Service status, available after model load and warmup. |
DELETE |
/streams/{stream_id} |
Close an idle stream session and forget its cached results. |
OpenAI-style WAV API¶
A limited subset of the OpenAI transcription and translation request contracts:
GET /v1/modelsreturns the single loaded local model.POST /v1/audio/transcriptionstakes multipart fieldsfile,model, and optionallanguageandresponse_format(jsonortext). JSON responses containtext. Language detection is automatic by default.POST /v1/audio/translationsis the same except it has nolanguagefield; it detects the speech language and translates to English.
Use the loaded local model name, or whisper-1 as an explicit compatibility alias
for it. This does not load OpenAI's hosted model or switch models per request.
Only uncompressed PCM WAV, mono or stereo, 8–48 kHz, 0.01–12 seconds, within a
5 MiB multipart envelope is supported. Convert or chunk other audio first. The
adapter retains native detail errors and HTTP status codes.
This example uses the official OpenAI Python SDK, targeting only the local server.
from openai import OpenAI
import os
client = OpenAI(base_url="http://127.0.0.1:8765/v1",
api_key=os.environ.get("CAPTION_API_KEY") or "local-unused")
with open("speech.wav", "rb") as audio:
result = client.audio.transcriptions.create(
model="small", file=audio, language="fr")
print(result.text)
Health¶
GET /health is available only after the model has loaded and the decoder has
actually warmed up. It reports readiness together with details such as the model,
device, compute type, sample rate, supported languages, modes, busy,
completed and failed. It also reports scheduler figures including
max_streams, workers, sessions, running, pending, queue settings and
counters such as rejected and queue_timeouts.
Native transcribe¶
POST /transcribe?language=es&mode=both
Required headers are Content-Type: application/octet-stream and
X-Caption-Local: 1, with optional X-Stream-ID and X-Request-ID (8–80 ASCII
letters, numbers, _ or -). The body is little-endian float32 mono PCM at
16 kHz, normalized to [-1, 1], 0.01–12 seconds, with no WAV header.
language defaults to en and accepts Whisper language codes or auto. mode
is transcribe (default), translate (English only) or both. A JSON response
includes text, transcript, translation, language, mode, timing values
and the request and stream IDs. Unrequested output fields are empty strings.
Rolling windows add window=1, final=0 and context_seconds=0.5 to decode an
unfinished window; final=1 (the default) commits the complete supplied window.
Streams and errors¶
One request may upload, queue or run per stream, and independent streams share
FIFO worker admission. Successful results are kept in memory for up to 120
seconds. DELETE /streams/{stream_id} with the X-Caption-Local: 1 header closes
an idle session immediately; a busy session returns 409.
Common status codes:
| Status | Meaning |
|---|---|
400 |
Invalid audio, language, mode, context or ID. |
401 |
Missing or incorrect service access token. |
403 |
Wrong or missing local header, or a foreign Origin. |
408 |
Upload exceeded the ten-second limit. |
409 |
A reused ID with different input. |
413 / 415 |
Oversized audio / wrong content type. |
429 |
Stream busy, capacity reached, or queue deadline exceeded. |
500 |
Inference failed. |
503 |
HTTP concurrency limit or restarting service. |
Related pages: Configuration, Relay and rooms and the Glossary.