server: add /v1/audio/transcriptions/details for transcript detail fields - #401
server: add /v1/audio/transcriptions/details for transcript detail fields#401CryptVenture wants to merge 1 commit into
Conversation
255eac1 to
c287387
Compare
|
@CryptVenture This is caused by legacy design, and we never touched it because no user requested it before. My concern is that existing pipelines may already depend on the current /v1/audio/transcriptions response schema, so adding extra fields by default could break them. A better solution is to add a separate opt-in endpoint, like POST /v1/audio/transcriptions/details, for the richer timestamp/detail response, and document the new endpoint clearly. |
|
Agreed on the compatibility risk — a caller that iterates the response object or asserts on its keys would break, and that is not worth it for a field nobody asked for. I will rework this as you describe: One question before I push, because the same argument cuts both ways. This PR also added
I will go with 1 unless you say otherwise. Either way the existing |
…elds 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
c287387 to
b32a523
Compare
|
Pushed the rework, and I went with option 1 as flagged above — nothing existing changes shape.
Verified on macOS/Metal with Parakeet TDT 0.6B v3, same 24 kHz input throughout:
|
Reworked per review:
/v1/audio/transcriptionskeeps its current response schema, and the richer response moves to an opt-inPOST /v1/audio/transcriptions/details.The problem
ASR models that align words, segment speech or separate speakers report that through
TaskResult::word_timestamps,speech_segmentsandspeaker_turns./v1/audio/transcriptionsserialisestextandtimingonly, so for those models the alignment is computed and then dropped on the way out of the server./v1/tasks/runalready serialises the arrays, so the data reaches one route and not the other.The route
Same request as
/v1/audio/transcriptions— JSON with a server-local path, or a multipart upload. The response is a superset of the plain one:textfirst,timinglast, withlanguage,segments,speaker_turnsandwordsin between where the model produced them.Spans are sample offsets because that is what the models report, so
sample_ratetravels with them, emitted only when at least one array is present.stream=truereturns 400 on this 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
/v1/tasks/runalready performed is factored intowrite_transcript_detail_fieldsand shared rather than duplicated.Compatibility
/v1/audio/transcriptionsand/v1/tasks/runproduce byte-identical responses tomain. Nothing existing changes shape.Verification
macOS, Metal backend, Parakeet TDT 0.6B v3 q8_0, same 24 kHz input to every request:
253 word timings that the plain route discards.
ctestpasses 40/40.Docs
app/server/README.mdgains a section for the route: request forms, the response example, a table of which field appears when, the sample-offset explanation, and the streaming restriction.README.mdgains the route in its endpoint list.