Repository navigation
fix(ios): recording resume after an interruption - #1257
Merged
Merged
Conversation
…ting a closed writer
SomePersonFromMars
force-pushed
the
fix/ios-recording-interrupted
branch
from
August 28, 2026 12:06
36d372e to
900e04b
Compare
…s actually delivered
SomePersonFromMars
force-pushed
the
fix/ios-recording-interrupted
branch
from
August 28, 2026 12:08
900e04b to
6283fb7
Compare
Also JS handler is only executed on an engine state change.
SomePersonFromMars
force-pushed
the
fix/ios-recording-interrupted
branch
from
September 2, 2026 12:06
534c3c0 to
3bd07bf
Compare
SomePersonFromMars
force-pushed
the
fix/ios-recording-interrupted
branch
from
September 2, 2026 12:09
3bd07bf to
86a9ae7
Compare
SomePersonFromMars
requested review from
closetcaiman and
maciejmakowski2003
and removed request for
closetcaiman
September 4, 2026 11:09
SomePersonFromMars
marked this pull request as ready for review
September 4, 2026 11:09
maciejmakowski2003
requested changes
Sep 4, 2026
maciejmakowski2003
left a comment
Collaborator
There was a problem hiding this comment.
could you perform the same research on android? in perfect world we would like to provide SotA for interruptions om both platforms.
mdydek
requested changes
Oct 1, 2026
mdydek
left a comment
Member
There was a problem hiding this comment.
I think we should in different PR implement also recoverable android from the interruption, because right now the only thing it does is sending event to the js about the interruption which would make both platforms behavior non uniform
SomePersonFromMars
removed this pull request from stack #1318
October 14, 2026 16:31
SomePersonFromMars
added this pull request to stack #1347
October 14, 2026 16:34
mdydek
requested changes
Oct 16, 2026
7 tasks
SomePersonFromMars
removed this pull request from stack #1347
October 19, 2026 13:47
SomePersonFromMars
added this pull request to stack #1353
October 19, 2026 13:47
closetcaiman
requested changes
Oct 19, 2026
closetcaiman
approved these changes
Oct 22, 2026
mdydek
approved these changes
Oct 22, 2026
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.
Closes #1220
observeAudioInterruptions(true)no longer replaces native recovery. NativeonInterruptionBegin/onInterruptionEndalways run. The flag only enables JSinterruptionevents, which matches the existingAudioManagerdocs. Apps that subscribed because observing used to skip native resume should not own engine recovery for a recorder (in particular, do not callRecorder.pause()onbegan- that moves the engine toPausedand disables the native retry). Playback can still pause onbegan. Native pauses onbegan, but it does not resume audio contexts.Introduced changes
Fixes iOS recording that never came back after an interruption. Updated library policy: the same take resumes when the app is in the foreground, or returns to it. Background restart after the interrupter leaves is best-effort; iOS can still refuse I/O while the app is backgrounded.
Responds to the issue
§1
onInterruptionEndnever activated the session; failure poisonedIdle; no input-node guardstartEngine).startAndReturnErrorfailure, stayInterruptedand return (do not setIdle). A later retry can run.Interrupted. The take is left as it was, and a later retry can run.shouldResume, according to the docs, only refers to playback resume. We choose to resume recording unconditionally, assuming that the user explicitly started it. The only exception is when playback should not be resumed: ideally, we would resume recording and leave playback paused. That is not trivial to implement, and the use case is uncommon, so it is safer not to resume in that case. A possible implementation is currently under development in Refactor/ios interruption policy #1346.§2 Docs vs behavior for
observeAudioInterruptionsobserveAudioInterruptions, an appropriate handler runs only whenAudioEngineactually transitioned to a new state. For example, if the engine wasInterrupted, the handler runs on a successful transition toRunning.§3 No-op
setActive:falsestill ran deactivationsetAudioSessionActivity(false)only calls session-deactivation handling if the session was actually managed and active beforesetActive. It no longer transitionsInterruptedtoPaused, which used to disableonInterruptionEnd.§3 / footnote -
resume()/ storeRecordingon a dead engineresume()still does not have a return type, but it is now guaranteed thatisRecording()is true if and only if the audio engine is not in an interrupted state and the recorder is actually running.AudioEngine'sonInterruptionEndrecovery afterAVAudioSessionInterruptionTypeEndedcan still fail. That can happen, for example, due to a race with a higher-priority app or internal iOS privacy policy. In that case we retry once the app returns to the foreground, which is then guaranteed by iOS to succeed.Consumer note -
mixWithOthers/CannotInterruptOthersplayAndRecordis required to avoidCannotInterruptOtherswhen activating in the background, and is not sufficient for background restart. The Record demo enablesmixWithOtherswithdefaultmode.Additional useful tweaks and fixes
WillEnterForegroundNotificationandDidBecomeActiveNotification. iOS guarantees that a foreground audio start succeeds. The retry uses a cachedshouldResumeflag.notifyInput:HardwareChangedis called before the engine starts, so the recorder matches the new format before the first buffer arrives.startIfNecessary, matching the recorder. A later recorder start must not play leftover source audio.observeAudioInterruptions(true); freeze the waveform onbegan, unfreeze only onended.Docs
AudioManagersubsection "Resume recording after an interruption".Manual tests and reproductions used while debugging
This issue is hard to reproduce with automated tests. During research and implementation I used the following manual tests, with the
apps/fabric-exampleapp and the included Recorder demo.Checklist