Audio intelligence is transcription with the speakers, the timing and the acoustics already in it. One pass over a recording returns the transcript, anonymous speaker labels, segment and word timestamps, per-word confidence, and an audibility reading that says whether a turn was on mic, off mic or too faint to trust. There is no separate diarization stage, no forced aligner to bolt on, and no chunk-and-normalize pipeline of your own to maintain. It rides the endpoint you already know. Name nur-stt-v1 and ask for verbose_json.
There is one transcription id, and it is the diarizing model: nur-stt-v1 returns speakers for a voice note and for an hour of meeting alike. Ask for verbose_json and they are there — no second id to opt into.

The payload

Speaker labels (S01, S02, …) are consistent inside one file and anonymous. They identify voices, not people, and they reset between files — the first voice heard in an upload is S01 in that upload and nowhere else.

Words

words is a flat, OpenAI-shaped array. Each entry carries segment_id and speaker, so you can regroup it into turns without a second pass. Word timing is on by default. Send timestamp_granularities[]=segment to skip the alignment pass, which is worth a few seconds of GPU on a long file. When alignment was asked for and could not run, the payload says so with words_unavailable: true rather than omitting the key — an absent key is indistinguishable from an older backend, and that ambiguity once hid a GPU out-of-memory behind a transcript that otherwise looked perfect.
confidence is acoustic support, not probability of correctness. Timing and confidence come from force-aligning the finished transcript back to the audio, so the number says how well the audio matches the word where it was placed — not what the recognizer believed. The two come apart on hard audio: on a noise-mixed clip the model transcribed every word correctly while this score collapsed. Read it as “the audio is difficult here, listen to it”, not “this word is probably wrong”, and measure it on your own material before you gate anything on it.

Audibility: which lines you can quote

Faint off-mic speech — a question from behind the camera, crew direction bleeding into a take — sits 30 dB or more under the dialogue. Whole-file loudness normalization cannot recover it, because integrated loudness is dominated by the loud material. This service normalizes adaptively in short frames instead, which does recover it: an utterance 35 dB down transcribes word-perfect and with the right speaker. That creates a second problem. After normalization every level looks the same, so the transcript alone cannot tell you which lines were actually on mic. The level is therefore measured on the pre-normalization signal, against the file’s own noise floor. In the payload above the presenter reads 41.4 dB SNR (on_mic) and the off-camera request reads 3.3 dB (faint). Both are fully transcribed, and afterwards you can tell them apart — which is what lets you quote one and not the other.

Silence, pace, language

A silent upload — b-roll, room tone — is answered by a voice-activity gate before the GPU is occupied: "text": "", empty segments, and "no_speech": true.

Sound events

Alongside the transcript the whole file is swept with an audio tagger and returned as scene: what sound occurs when, for the entire duration, rather than one dominant label per asset.
label is one of music, speech, crowd, ambience, room_tone, sfx; raw_label is the strongest underlying class in that region; role applies to music only, bed when dialogue runs across it and featured otherwise. Events overlap on purpose. Dialogue over a music bed in a room with traffic outside is three simultaneous answers, and a timeline reporting one winner per moment throws two of them away — a speech clip mixed with broadband noise came back as 100% ambience, the speech erased. So each bucket gets its own run of events, and music and speech covering the same seconds is the normal case. Shares in scene_summary overlap for the same reason and sum above 1.

Keeping a run

POST /v1/audio/transcriptions is a pure relay: it returns the result and keeps nothing. POST /v1/speech/transcriptions is the library — one upload that both transcribes and files the run, so it has a row, its audio, and a place to come back to.
One upload does both, because letting the browser transcribe and then post the result back would send a 90-minute file over the wire twice. stream defaults to true here; pass stream=false for a single JSON body.

Naming the speakers

S01 is not a name. Operator names are stored beside the model’s own labels, never over them, so re-running or re-reading the result never loses either:
The detail read returns speaker_names next to result, and it is yours to render. Deleting a run erases the uploaded audio first and the row second. If storage refuses, nothing is deleted and the delete can be retried — the other order would strand an audio object that nothing references and nothing can find again.

When the library fails

/v1/speech/* is not one of the OpenAI-shaped routes, so it answers in two envelopes rather than one. The gates it shares with /v1/audio/transcriptions keep the OpenAI envelope; everything the route raises itself uses FastAPI’s plain {"detail": …}. A bad form field here is a 422, not the 400 you get one endpoint over. Creating a run applies the same gates as the OpenAI-compatible route, and those keep the OpenAI envelope: rate_limit_exceeded, free_tier_daily_limit and insufficient_quota at 429, plus model_not_found at 404 and model_unavailable at 503. A client here needs to read both shapes.

Limits

Speaker labels are per file. Two recordings of the same meeting do not agree about who S01 is, so map labels to people once per run and store the mapping with the run rather than inferring it again.

Next

Transcribe a meeting

The recipe end to end, including saving and naming.

Speech to text

Plain transcription, and the request fields you share with it.

Sessions

The other kind of record: live conversations.

Compliance

Recording and consent duties that come with keeping audio.