ROCm / ROCm/FastFlowLM

ASR: /v1/audio/transcriptions ignores response_format — timestamps are computed internally but discarded

Open
#637 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
1.9k
Forks
152
Avg merge
4h 14m
Merged PRs (30d)
11

Description

Hi! Thanks for FLM — the NPU ASR path has been really useful for me.

While reading the source I noticed that /v1/audio/transcriptions always returns a minimal {model, text} object, and that most of the pieces needed for OpenAI's verbose_json response already exist inside the Whisper engine but are dropped at the REST layer. Filing this in case it's simply "not wired up yet" rather than a deliberate decision — apologies if it's already on the roadmap.

Checked against master @ 8b8399c. Environment: FLM v0.9.45, Windows, AMD Ryzen AI 5 340 — though this comes from reading the source rather than a runtime failure, so the environment probably isn't relevant here.

Current behavior

response_format is never read on the server side (grepping for response_format / verbose_json in src/ returns nothing), so a client asking for verbose_json silently gets plain text back. Anything that needs segment timing has to re-chunk the audio client-side and stitch the offsets back together.

Handler: https://github.com/FastFlowLM/FastFlowLM/blob/8b8399c1f259d31bba2c42c2e3038c2b69856b89/src/server/rest_handler.cpp#L1290-L1301

std::pair<std::string, std::string> audio_result =
    this->whisper_engine->generate(Whisper::whisper_task_type_t::e_transcribe, true, false, std::cout);
//                                                                            ^^^^  ^^^^^
//                                                    enable_time_stamp=true, return_time_stamp=false

std::string audio_context = audio_result.first;
...
response = { {"model", model}, {"text", audio_context} };

What the engine already produces

1. Timestamps are computed. When return_time_stamp is true, decoded timestamps are offset per chunk and appended to the result string:
https://github.com/FastFlowLM/FastFlowLM/blob/8b8399c1f259d31bba2c42c2e3038c2b69856b89/src/common/whisper/modeling_whisper.cpp#L170-L174

2. enable_time_stamp cannot be the exposure switch — it is structurally required for the sliding-window chunking, since the next chunk boundary is derived from the last timestamp:
https://github.com/FastFlowLM/FastFlowLM/blob/8b8399c1f259d31bba2c42c2e3038c2b69856b89/src/common/whisper/modeling_whisper.cpp#L233

So the only knob that controls exposure is return_time_stamp, and it is hardcoded to false at the single call site.

3. The detected language is already returned, but the handler only uses .first:
https://github.com/FastFlowLM/FastFlowLM/blob/8b8399c1f259d31bba2c42c2e3038c2b69856b89/src/common/whisper/modeling_whisper.cpp#L247

return std::make_pair(result, langmap::to_language_name(language_detected));

4. Audio duration is already knownload_audio() logs Length of audio: N seconds.

Suggestion

Read response_format in handle_openai_audio_transcriptions, and for verbose_json pass return_time_stamp=true, parse the <|x.xx|> markers out of the result string into segments[], and fill language / duration from what the engine already hands back:

{
  "task": "transcribe",
  "language": "japanese",
  "duration": 123.4,
  "text": "...",
  "segments": [
    { "id": 0, "start": 0.00, "end": 4.20, "text": "..." }
  ]
}

json and text formats would keep the current behavior, so this should be backward compatible.

Why it matters

Without segments, subtitle generation and long-audio alignment require re-implementing chunking on the client side, which duplicates work the engine is already doing (and can drift from the engine's own chunk boundaries).

Related: #234 — surfacing the detected language would partly address that request as well.

Thanks for the great work!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/server/rest_handler.cpp at handle_openai_audio_transcriptions and trace the pair returned by src/common/whisper/modeling_whisper.cpp. Check how response_format and return_time_stamp are handled; done when verbose_json exposes the requested language, duration, text, and segments while json and text retain their current behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
api, backend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.