Speech to Text

Paddock serves speech models on two surfaces: one request for a file you already have, and a WebSocket for audio that is still being spoken. Both follow OpenAI's wire format, so existing clients and SDKs work unchanged.

Transcribing A File

POST /v1/audio/transcriptions takes multipart/form-data.

FieldMeaning
fileThe audio. Containers accepted: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, webm.
modelThe loaded speech model.
response_formatjson (default), text, verbose_json, srt or vtt.
languageISO 639-1 hint. Optional.
promptContext for the decode. On Granite Speech this field carries the instruction and therefore selects the task.
temperatureDefaults to 0, which is greedy.
timestamp_granularities[]segment, word, or both.
streamtrue streams the answer as it is decoded.

Parameters in the OpenAI specification that Paddock does not serve are refused by name rather than ignored, and a field that is not in the specification at all is refused the same way the JSON endpoints refuse an unknown key. You never get a quietly different answer than the one you asked for.

Streaming A File

With stream=true the response is a sequence of transcript.text.delta events followed by one transcript.text.done. The deltas concatenate to exactly the text the terminal event carries, so a client that appends every delta ends up holding the final transcript with no reconciliation step.

srt and vtt refuse to stream. Half a subtitle document is not half an answer.

Timestamps

Timestamps are opt-in through timestamp_granularities[], and which of these a checkpoint can answer is a property of that checkpoint. The server publishes it on GET /v1/models, so a client can read the capability instead of discovering it through a 400. Asking a model for a granularity it cannot produce returns a refusal naming the model, never an empty segments array.

On Whisper, segment changes the decode: the model is told to emit times and its output is constrained by the timestamp grammar. That is why it is opt-in, since a plain transcription keeps the exact prompt the accuracy gates were measured against. Asking for word adds a second, teacher-forced alignment pass over each window, which is where OpenAI's note about word timestamps costing extra latency comes from; it does not change the transcript. Both compose, giving a top-level words[] of {word, start, end} alongside segments[].

On Granite Speech Plus, word timing is a different mechanism: the model is asked for the times and writes them into its own answer, so here the granularity does change the transcript. IBM's model card is explicit that the timestamp mode drops punctuation and capitalization, which is also why segment is refused on that family, since without punctuation there are no sentence boundaries to cut cues on.

Live Transcription

GET /v1/realtime?intent=transcription upgrades to a WebSocket carrying OpenAI's Realtime transcription session. A microphone has no end until the speaker stops, so it cannot be a request body; this is the shape OpenAI defined for it and clients already handle it.

DirectionEvents
Client to serversession.update, input_audio_buffer.append, input_audio_buffer.commit, input_audio_buffer.clear
Server to clientsession.created, session.updated, conversation.item.input_audio_transcription.delta, conversation.item.input_audio_transcription.completed, input_audio_buffer.committed, input_audio_buffer.cleared, error

What Live Text Guarantees

Whisper's encoder reads a fixed 30-second window, so something has to decide which words are safe to show before the sentence is finished. Paddock commits only the longest prefix that two consecutive passes agree on, a policy known as LocalAgreement-2.

Words already shown are never retracted, and the deltas concatenate to the completed transcript exactly as they do on the file endpoint. What follows from that: completed is not the same text you would get by transcribing the whole recording in one pass. It is the committed prefix plus the final pass's tail, and that prefix was decided from shorter buffers. Not rewriting what you already read is what a delta stream buys, and this is what it costs.

A closed utterance runs a final, authoritative pass, and completed carries a paddock_verbose object holding exactly what verbose_json would return for that utterance's audio, including segment times, word times and per-word confidence. Cost therefore scales with speech rather than with recording length: a long session settles as it goes instead of being re-transcribed at the end.

Aligning A Transcript You Already Have

POST /v1/audio/alignments answers a different question from transcription: given the audio and the words, when was each one said. That is what you need to caption an existing script, to check a proofread transcript against the recording, or to jump to the moment a phrase occurs.

Multipart form: file for the audio, text for the transcript to align, and optionally language. The reply's words array is the same {word, start, end} shape in seconds that verbose_json uses for transcription word times, so anything that already reads those needs no new parser.

OpenAI has no alignment endpoint, so this one is Paddock's own. It borrows the word shape and nothing else, which is the only part worth borrowing.

Its Two Honest Limits

The model addresses time in fixed classes over a bounded budget, which caps the clip it can align at roughly 6.7 minutes on the 0.6B. A longer clip is refused with the cap stated in the message rather than truncated to fit.

Japanese and Korean are refused outright. Aligning them properly needs tokenizers that understand word structure, which this build does not carry, and the default splitter would hand back clause-sized "words" that look like an answer and are not one. Languages outside the model's trained eleven are accepted and flagged: the response carries language_supported: false, because the alignment may still be useful and you should be the one deciding that.

Models

Six speech models ship in the catalog: Whisper fine-tunes for Swedish, Norwegian and Danish, plus the multilingual Qwen3-ASR and Granite Speech families. See Supported Models for the list and what each one is good at.