Fix: dictation cancels itself immediately when the input is a Bluetooth headset - #20
Open
katkrasner wants to merge 1 commit into
Open
Fix: dictation cancels itself immediately when the input is a Bluetooth headset#20katkrasner wants to merge 1 commit into
katkrasner wants to merge 1 commit into
Conversation
Any AVAudioEngineConfigurationChange during recording dropped the buffer and cancelled. Opening the input on a Bluetooth headset makes macOS switch it from A2DP to HFP, which fires that notification within milliseconds of engine.start() — so on such a device every dictation cancels itself the instant it begins, with no visible cause. Tested with a Shokz OpenRun Pro 2 as the default input, where FastWord could not record at all before this change. start() is split so buildEngine() can re-run against the new device mid-recording, keeping the audio captured so far. Cancelling stays as the fallback for a failed rebuild, and a budget of three rebuilds stops a device that keeps renegotiating from looping. The app also asks for microphone access at launch rather than relying on the system to prompt when the engine first starts, and the input format, rebuilds and cancel reasons are logged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On a Mac whose default input is a Bluetooth headset, dictation cancels itself the instant it starts. The HUD never appears, nothing is transcribed, and there is no error — it just does nothing.
The cause is in
Recorder.installConfigChangeObserver. AnyAVAudioEngineConfigurationChangeduring recording is treated as "the hardware went away": the buffer is dropped, the engine torn down, andonHardwareChangecancels the dictation.But that notification is not only fired when someone unplugs headphones. Opening an input stream on a Bluetooth headset makes macOS switch the device from A2DP to HFP, which fires the notification within milliseconds of
engine.start(). So the recording cancels itself before the user has said a word.Reproduced with a Shokz OpenRun Pro 2 (16 kHz HFP) as the default input device, where FastWord could not record at all. Log from an instrumented build:
Change
start()is split sobuildEngine()can re-run against the new device mid-recording, keeping the audio captured so far. The dictation continues across the device switch instead of dying.Cancelling is kept as the fallback when the rebuild itself fails, and a budget of three rebuilds per recording stops a device that keeps renegotiating from looping forever. Unplugging headphones mid-sentence still behaves sensibly: the engine rebinds to the new default input.
Also in here, because it is the same class of silent failure:
Testing
Built and run on macOS 26, Apple Silicon. Verified dictation now works end to end with the Bluetooth headset as default input, and that it still works with the built-in microphone. Switching the input device mid-recording keeps the recording alive rather than discarding it.