Skip to content

fix(asr): 修复 Windows 本地长语音只识别前段#769

Open
Duyi-Wang wants to merge 2 commits into
Open-Less:betafrom
Duyi-Wang:dev
Open

fix(asr): 修复 Windows 本地长语音只识别前段#769
Duyi-Wang wants to merge 2 commits into
Open-Less:betafrom
Duyi-Wang:dev

Conversation

@Duyi-Wang

@Duyi-Wang Duyi-Wang commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

User description

摘要

修复 Windows 本地 ASR 在长语音场景下可能只识别前一段的问题。

主要原因是 foundry-local-whisper 使用 Whisper 系模型,单次解码窗口约 30 秒;当录音超过这个窗口时,单次把整段 WAV 交给 Foundry SDK 可能只返回前段结果。这个 PR 将 Foundry Local Whisper 的 PCM 输入按 30 秒分片转写,再合并分片文本;同时把 Windows 本地 ASR 的转写超时从固定 30 秒改为按音频时长动态增长。

未关联 issue。

修复 / 新增 / 改进

  • foundry-local-whisper 录音结束后按 30 秒 PCM chunk 分片,逐段生成临时 WAV 并调用 Foundry SDK。
  • 复用 Whisper batch ASR 的 chunk split / transcript join 逻辑,避免中英文、CJK 标点拼接时产生明显断裂。
  • 为 Foundry / Sherpa provider 增加 buffer_duration_ms(),coordinator 可按实际录音长度计算 timeout。
  • 普通听写、QA、overlay QA、历史重新转录路径都接入 Windows 本地 ASR 动态 timeout。
  • 将 Windows Foundry / Sherpa 本地 ASR timeout 调整为 max(30s, ceil(audio_s) + 20s),避免长音频撞固定 30 秒超时。
  • 增加 Foundry 分片、buffer duration、Sherpa buffer duration、Windows 本地 ASR timeout 相关测试。

兼容

  • 不包含:

    • 云端 ASR 协议变更。
    • 录音采集链路变更。
    • 插入 / polish 流程变更。
    • 用户配置迁移或模型配置变更。
  • 对现有用户 / 本地环境 / 构建流程的影响:

    • 短语音仍使用 30 秒 timeout 保底,行为基本不变。
    • 长语音在 foundry-local-whisper 下会拆成多段本地识别,整体耗时会随音频长度增加,但可以覆盖完整录音。
    • sherpa-onnx-local 仅调整 timeout 预算,不改变识别输入和模型调用方式。

测试计划


PR Type

Bug fix


Description

  • Split Foundry Local Whisper PCM into 30s chunks to prevent truncation of long recordings

  • Added dynamic transcribe timeout (max(30s, ceil(audio_s)+20s)) for Windows local ASR

  • Exposed buffer_duration_ms() from Foundry and Sherpa providers

  • Applied dynamic timeout to dictation, QA, overlay QA, and re-transcription paths


Diagram Walkthrough

flowchart LR
  audio["Recorded PCM (long)"] --> split["Split into 30s chunks"]
  split --> chunk1["Chunk 1"] & chunk2["Chunk 2"] & chunkN["Chunk N"]
  chunk1 --> transcribe1["Transcribe with remaining timeout"]
  chunk2 --> transcribe2["Transcribe with remaining timeout"]
  chunkN --> transcribeN["Transcribe with remaining timeout"]
  transcribe1 & transcribe2 & transcribeN --> join["Join transcripts"]
  join --> result["Full transcript"]
  audio -- "buffer_duration_ms()" --> timeout["Dynamic timeout = max(30s, ceil(audio_s)+20s)"]
  timeout --> transcribe1 & transcribe2 & transcribeN
Loading

File Walkthrough

Relevant files
Enhancement
foundry_provider.rs
Chunk Foundry Whisper PCM into 30s segments                           

openless-all/app/src-tauri/src/asr/local/foundry_provider.rs

  • Added FOUNDRY_WHISPER_CHUNK_LIMIT_MS constant (30s) and
    buffer_duration_ms() method
  • Modified transcribe() to split PCM into 30s chunks and transcribe each
    with remaining deadline timeout
  • Added helper remaining_transcribe_timeout() and tests for chunking,
    timeout calculation, and buffer reporting
+111/-17
sherpa_provider.rs
Add buffer_duration_ms to Sherpa ONNX provider                     

openless-all/app/src-tauri/src/asr/local/sherpa_provider.rs

  • Added buffer_duration_ms() for both Offline (PCM buffer) and Online
    (worker audio bytes) modes
  • Added test to verify buffer duration reported without consuming buffer
+25/-0   
whisper.rs
Export PCM split and transcript join functions                     

openless-all/app/src-tauri/src/asr/whisper.rs

  • Made split_pcm_by_duration() and join_transcript_chunks() pub(crate)
    for reuse by Foundry provider
+2/-2     
coordinator.rs
Replace fixed timeouts with dynamic per-audio timeout       

openless-all/app/src-tauri/src/coordinator.rs

  • Unified fixed timeout functions into dynamic
    windows_local_asr_transcribe_timeout(audio_secs)
  • Updated Foundry and Sherpa transcribe calls in
    re_transcribe_current_session to use audio-relative timeout
  • Updated tests: short audio floors at 30s, long audio scales (e.g., 65s
    → 85s)
+32/-23 
dictation.rs
Use dynamic timeout in dictation end session                         

openless-all/app/src-tauri/src/coordinator/dictation.rs

  • Updated end_session for Foundry Local Whisper and Sherpa ONNX to
    compute timeout from buffer_duration_ms()
  • Added logging of audio duration and timeout
+16/-8   
qa_session.rs
Use dynamic timeout in QA transcription paths                       

openless-all/app/src-tauri/src/coordinator/qa_session.rs

  • Updated transcribe_overlay_dictation_asr and end_qa_session for
    Foundry and Sherpa to compute dynamic timeout
  • Added logging in QA transcription paths
+22/-16 

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

(Review updated until commit 3f2c6a4)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ No major issues detected

@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 3f2c6a4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants