You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
server: add /v1/audio/transcriptions/details for transcript detail fields
ASR models that align words, segment speech or separate speakers report that
work through TaskResult::word_timestamps, speech_segments and speaker_turns.
/v1/audio/transcriptions serialises text and timing only, so for those models
the alignment is computed and then discarded on the way out of the server.
Rather than widen the existing response, which callers already build against,
this adds an opt-in route with the same request shape. /v1/audio/transcriptions
and /v1/tasks/run are byte-identical to before.
The detail response is a superset of the plain one: text first, timing last,
with language, segments, speaker_turns and words in between where the model
produced them. Spans are sample offsets because that is what the models report,
so sample_rate travels with them and is emitted only when at least one of the
arrays is present.
stream=true is rejected with a 400 on the detail route. The SSE response carries
transcript deltas only and has nowhere to put the arrays, so accepting the
request would return none of what the route exists to return.
The serialisation the generic task route already performed is factored into
write_transcript_detail_fields and shared, rather than duplicated.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ATa5YkLUPMDPRL7w1gCo9p
Copy file name to clipboardExpand all lines: app/server/README.md
+38Lines changed: 38 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -380,6 +380,44 @@ The stream emits `transcript.text.delta` events, one final `transcript.text.done
380
380
381
381
Note that `stream=true` streams the *output* of an already-uploaded file: the whole recording is sent first, and the deltas describe decoding it. It shortens time-to-first-token on long audio, but nothing can appear while the speaker is still talking. For that, use the live endpoint below.
382
382
383
+
### `POST /v1/audio/transcriptions/details`
384
+
385
+
Same request as `POST /v1/audio/transcriptions` — JSON with a server-local path, or a `multipart/form-data` upload — with a richer response. Use it when the model produces timestamps or speaker labels and the caller wants them.
386
+
387
+
`/v1/audio/transcriptions` returns `text` and `timing` and nothing else, so a model that aligned every word or separated speakers has that work discarded on the way out. This route returns those fields instead. The response schema of the plain route is unchanged; existing clients see exactly what they see today.
`text` and `timing` are always present and match the plain route. The rest appear only when the model produced them:
408
+
409
+
| Field | Present when | Contents |
410
+
|---|---|---|
411
+
|`language`| the model reports a detected or configured language | Language code. |
412
+
|`segments`| the model produces speech segments |`start_sample`, `end_sample`, `confidence`, and `text` where the segment carries it. |
413
+
|`speaker_turns`| the model diarizes |`start_sample`, `end_sample`, `speaker_id`, `confidence`, and `text` where present. |
414
+
|`words`| the model aligns words |`word`, `start_sample`, `end_sample`, `confidence`. |
415
+
|`sample_rate`| any of the three arrays above is present | Rate the sample offsets are counted in. Divide an offset by it for seconds. |
416
+
417
+
Spans are sample offsets rather than seconds because that is what the models report; `sample_rate` is what converts them, which is why it only appears alongside them.
418
+
419
+
`stream=true` is rejected with a 400 on this route: the SSE response carries transcript deltas only, so it has nowhere to put the detail arrays. Use `/v1/audio/transcriptions` for a streamed transcript.
420
+
383
421
### `POST /v1/audio/alignments`
384
422
385
423
Multipart forced-alignment request using uploaded audio bytes and a known transcript. Use this when the server cannot see the client's local audio path, for example when the server is remote or running in Docker.
0 commit comments