fix: transcription pipeline hangs forever with audio_feedback enabled (WASAPI stall + unbounded recorder waits)#1713
Conversation
Opening a WASAPI output stream (or enumerating output devices for an explicit selection) on every chime races concurrent audio session state. When that call wedges, it takes the rest of the audio stack down with it: the transcription task blocks inside the microphone stream shutdown and the pipeline stays "busy" forever (Transcribing... overlay never resolves, only killing Handy recovers). Move playback to a dedicated long-lived worker that opens the output stream once (pre-warmed at startup, while no transcription is running) and reuses it, recreating only on device change or playback error. Blocking callers (start-chime -> mute sequencing, test sound) now wait with a bounded timeout, so even a wedged audio stack cannot stall the callers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Field testing of the persistent-stream fix surfaced the second half of the failure chain. When the output stream turns into a zombie after a device state change (frozen audio clock, no error -- observed with a wireless headset), the chime worker used to wait on it forever; the wedged WASAPI state then stopped capture callbacks, and the mic worker only serviced commands on chunk arrival -- so Stop sat unread and the pipeline hung "busy" forever even though the chime path was already fire-and-forget. - mic worker: service commands on a 250ms tick even when the capture callback delivers nothing (wedged engine, dead device) - recorder.stop(): bounded 5s wait -- losing one utterance is recoverable, a forever-busy pipeline is not - recorder.close(): bounded join via reaper thread; a stream drop that blocks on a wedged engine parks a disposable thread, not the caller - chime playback: bounded 5s wait instead of sleep_until_end(); a stalled sink marks the stream as zombie - zombie streams are dropped on throwaway threads and recreated fresh Worst-case degradation under any WASAPI misbehavior is now one lost chime or one lost utterance, never a stuck app. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nges The persistent output stream keeps playing to the device it was opened on, so after the user switches the Windows default output (headphones <-> speakers) chimes kept going to the old device. Before each use of a Default-selection stream, resolve what the OS default currently points to (a cheap device-name query, not a stream creation) and recreate the stream when it moved. Explicit device selections are unaffected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
So I'm not super happy with the changes as they were submitted. Mostly they didn't compile which is a pretty bad sign. I'm not sure how this was tested, at least on MacOS this does not compile as submitted I've reverted the audio feedback related changes. Please give the branch a try in its current state and see if the bug is fixed. I would rather have more targeted changes towards the bug than rewriting things at the moment. |
|
Thanks for reverting the part that didn't build — that one's on me, I only compiled on Windows so I missed that cpal's stream is The recorder changes you kept are the actual fix for the hang. I've been running exactly these on Windows daily for over a week (audio feedback on, hundreds of transcriptions) with zero hangs, where before it was every 2–30. So this branch as-is fixes it for me. I redid the audio-feedback half properly and cross-platform as a separate PR #1740 (green Linux CI on my fork, and I verified the macOS build compiles and links — it only fails at codesign because my fork has no Apple cert) so this one can stay focused on the recorder fix. Up to you whether it's worth taking. |
Before Submitting This PR
Please confirm you have done the following:
If this is a feature or change that was previously closed/rejected: N/A — bug fix requested by the maintainer in #1712.
Human Written Description
(author's own words, translated from Russian)
Related Issues/Discussions
Fixes #1712
Likely the same underlying family: #1213, #1228, #1349 (analysis in #1712)
Community Feedback
The maintainer asked for this patch in #1712: "If you have a patch would love to see it and pull it in". #1213/#1228/#1349 contain independent confirmations of the symptom.
Testing
Field-tested on Windows 10 (Ryzen 7 9800X3D, RTX 5070, USB fifine mic, wireless headset + speakers):
WARNlog lines and recovered on its own, which is exactly the designed worst case (one lost chime / one lost utterance, never a stuck app).cargo clippyclean on the touched files,cargo fmtapplied.Commit-by-commit rationale and full log forensics are in #1712. The three commits are independent and can be cherry-picked separately if you want only part of this.
I'd appreciate additional testing on macOS/Linux — the recorder changes (bounded waits, command tick) are cross-platform, while the WASAPI-specific observations are Windows-only.
Screenshots/Videos (if applicable)
N/A — sanitized log excerpts are in #1712.
AI Assistance
If AI was used:
Co-Authored-By: Claudetrailer.