Skip to content

fix(react-native): re-arm iOS mic capture unit between sequential WebRTC sessions - #993

Open
mahmudsudo wants to merge 1 commit into
elevenlabs:mainfrom
mahmudsudo:main
Open

mahmudsudo wants to merge 1 commit into
elevenlabs:mainfrom
mahmudsudo:main

Conversation

@mahmudsudo

Copy link
Copy Markdown

Closes #991

Problem

On a physical iPhone, the second (and subsequent) sequential WebRTC conversation captures only silence. The microphone track is live, enabled, and unmuted at the WebRTC level ; bytesSent increments and LiveKit reports the engine running but total audio energy is zero and the agent receives only ....

Root cause: The React Native setup strategy calls AudioSession.stopAudioSession() at the end of each session and AudioSession.startAudioSession() at the start of the next. On iOS, this deactivates and reactivates the AVAudioSession, but the RTCAudioSession's input capture unit is not automatically re-armed when the new LiveKit peer connection publishes its mic track. The hardware tap is stalled.

The reporter confirmed this by manually muting then unmuting: audio resumed immediately within the same track, without any route change. This is the critical signal — a LiveKit-level mute/unmute causes the native RTCAudioSession to call setRecordingEnabled:YES again, which restarts the capture unit.

Fix

After createConnection() resolves (room connected, mic track published), apply an automatic mute → unmute microcycle on localParticipant when running on iOS in a voice session:

async function iosRearmMicrophone(connection: WebRTCConnection): Promise<void> {
  const room = connection.getRoom();
  await room.localParticipant.setMicrophoneEnabled(false);
  await room.localParticipant.setMicrophoneEnabled(true);
}

This runs before attachNativeVolume and before the conversation is considered ready, so it is invisible to the user (~1–2 async ticks at session start, before the agent begins listening).

Guards:

  • Platform.OS === "ios" — Android is unaffected and unchanged
  • !options.textOnly — no mic track is published in text-only sessions; no-op there
  • try/catch — failure is non-fatal and logged via console.warn; the session continues

Changes

File Change
packages/react-native/src/index.react-native.ts Add iosRearmMicrophone() helper; call it in reactNativeSessionSetup after createConnection() on iOS voice sessions
packages/react-native/CHANGELOG.md Add unreleased patch entry referencing #991

Testing

This issue only reproduces on a physical iPhone (not Simulator — Simulator has no AVAudioSession hardware stall). The recommended validation steps from the issue reporter:

  1. Build a native Expo development client for iPhone using the official examples/react-native-expo app with this patch applied
  2. Start a conversation, speak, confirm the agent responds, call endSession()
  3. Wait for provider status disconnected
  4. Immediately start a second conversation and speak
  5. Confirm bytesSent and audioLevel are non-zero for session 2
  6. Repeat for 10 consecutive sessions

Expected (with fix): all sessions capture and transmit microphone audio normally
Expected (without fix): sessions 2+ show audioLevel: 0, bytesSent << session 1

Related

@cursor

cursor Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

PR Summary

Low Risk
Scoped to iOS voice WebRTC session startup with guarded, best-effort mic toggle; no API or auth changes, though a failed re-arm could still leave the known silent-mic bug on that call.

Overview
Fixes silent microphone on the 2nd+ back-to-back WebRTC voice call on physical iPhones (#991). After stopAudioSession() / startAudioSession() between calls, iOS can leave the RTCAudioSession input tap stalled even though the LiveKit mic track looks live.

The React Native voice setup strategy now runs an automatic mute → unmute on localParticipant right after createConnection() for iOS non–text-only WebRTC sessions (iosRearmMicrophone), before native volume attach—mirroring the manual toggle that restores capture. Failures are non-fatal (console.warn); Android and text-only sessions are unchanged. CHANGELOG documents the patch under Unreleased.

Reviewed by Cursor Bugbot for commit 5c8f5e2. Bugbot is set up for automated code reviews on this repo. Configure here.

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.

iOS: second sequential WebRTC call publishes microphone but captures silence

1 participant