fix: stop the microphone when a local audio track is stopped before joining a room - #1216
Venomexeno wants to merge 2 commits into
Conversation
- Introduced a mechanism to hold native audio recording sessions, allowing multiple tracks to share the same recording instance. - Updated startCapture and stopCapture methods to manage the recording state and ensure proper resource release. - Added NativeRecordingHolders class to track active recording holders and control when to stop recording. - Improved error handling during audio recording initialization. This change optimizes audio capture processes and prevents unnecessary recording sessions from being initiated.
There was a problem hiding this comment.
Devin Review found 1 potential issue.
1 flag not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)
| /// Process-wide because [Native.startLocalRecording] starts one audio device | ||
| /// module, shared by every local audio track (pre-join mic, room mic, | ||
| /// pre-connect buffer). | ||
| static final NativeRecordingHolders _nativeRecordingHolders = NativeRecordingHolders(); |
There was a problem hiding this comment.
🔴 Failed pre-connect leaves permanent holder
When pre-connect fails after capture starts, _nativeRecordingHolders retains the abandoned track. reset drops it without calling stop(), so later microphones never stop native recording.
Learn more
A successfully started pre-connect track adds itself to the process-wide holder set. If the operation wrapped by withPreConnectAudio then throws, stopRecording stops the native recorder directly but never stops the track. reset then clears _localTrack, while the static set keeps the object reachable forever. Every later track can add and remove itself, but the abandoned entry prevents the set from becoming empty.
Example: A pre-connect track starts, then Room.connect fails. A later pre-join microphone starts and stops normally, but removing it leaves the abandoned pre-connect holder, so Native.stopLocalRecording() is never called.
Recommended fix: Route pre-connect failure cleanup through the owned LocalAudioTrack.stop() before clearing _localTrack. Remove the direct native stop from that path so holder removal and native shutdown remain one atomic lifecycle.
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
startCapture()opens the native audio device module directly. Stopping the MediaStreamTrack does not close it, so a pre-join microphone keeps recording afterstop()/dispose().Test plan
flutter test test/track/native_recording_holders_test.dartUntitled.mp4