Skip to content

fix(ios): recover a silently stopped AVAudioEngine after a configuration change - #621

Open
mdridley wants to merge 1 commit into
llfbandit:mainfrom
mdridley:fix/ios-engine-config-change
Open

fix(ios): recover a silently stopped AVAudioEngine after a configuration change#621
mdridley wants to merge 1 commit into
llfbandit:mainfrom
mdridley:fix/ios-engine-config-change

Conversation

@mdridley

@mdridley mdridley commented Aug 18, 2026

Copy link
Copy Markdown

Problem

On iOS, RecorderStreamDelegate only observes AVAudioSession.interruptionNotification. A route change (headset connect/disconnect, another app reconfiguring the shared session) posts AVAudioEngineConfigurationChangeNotification instead, which stops the engine without any interruption ever firing — capture ends silently, with no state change for callers to observe. AVAudioEngine does not restart itself after this notification; per Apple's docs the caller is expected to reinstall the tap against the (possibly changed) input format and start the engine again.

Fix

Adds an observer for AVAudioEngine.configurationChangeNotification scoped to the engine instance. On fire: remove the tap, re-read inputNode.inputFormat, rebuild the AudioStreamProcessor against it, reinstall the tap, and restart the engine — the same sequence start() already does. On success this calls onRecord() same as the interruption-resume path, so callers observing RecordState see the recovery. On failure it calls stop() rather than leaving the engine silently wedged.

Opt-in via a new IosRecordConfig.restartOnEngineConfigurationChange (default false), so this is a no-op for existing callers and only changes behavior for those who ask for it.

Testing

Not yet device-tested — I'm about to wire this into my own app via a git override on this branch and will report back with real results (route changes, Bluetooth connect/disconnect, another app taking the session) once I have them. Opening the PR now for early feedback on the approach/flag naming while I do that.

…ion change

A route change, or another app reconfiguring the shared session, can stop
AVAudioEngine without ever posting an AVAudioSession interruption — capture
ends silently with no state change to observe. AVAudioEngine does not
restart itself; the input tap must be reinstalled against the (possibly
changed) input format and the engine started again.

Opt-in via IosRecordConfig.restartOnEngineConfigurationChange, defaulting
to false to keep this a no-op for existing callers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant