Skip to content

Bug: twilio-video keeps audio/video streams alive after room.disconnect() when accepting a second call on iOS (Capacitor + React) #2195

@Abhiranjanchaurasia

Description

@Abhiranjanchaurasia

Description
We are facing an issue with twilio-video.js on iOS where audio and video streams remain active even after calling room.disconnect() and removing all published tracks.
This issue consistently occurs when accepting a second call after a previous call, especially when the app is backgrounded and foregrounded. As a result, iOS continues to show the microphone/camera usage indicator in the status bar, even though no active room exists.

Environment

  • twilio-video: (2.34.0)
  • Platform: iOS (iOS v26.2)
  • Framework: React (v19)
  • Wrapper: Capacitor (v8)
  • Build: Production build (npm run build)
  • iOS WebView: WKWebView (via Capacitor)

Steps to Reproduce

  1. Clone and configure the provided React sample project. Repository link: https://github.com/Abhiranjanchaurasia/TwilioVideoReactSample

  2. Make sure the root folder has backend and frontend.
    Configure the backend environment variables:

  3. Create a .env file and add the following:

  • TWILIO_ACCOUNT_SID="XXXXXXX"
  • TWILIO_API_KEY="XXXXXXX"
  • TWILIO_API_SECRET="XXXXXXX"
  1. Important: Update the backend API base URL to use your local machine IP address
- ❌ http://192.168.1.42:3001
- ✅ http://<YOUR_LOCAL_IP>:3001
  1. Start backend
- cd backend
- npm install
- npm run start:dev
  1. Start frontend, build and sync the app:
- npm install
- npm run build
- npx cap sync
- npx cap open ios
  1. Run the app on a real iOS device
  2. Start the first video/audio call
  3. Move the app to the background, i.e., try to open another app while the call is in progress, and make sure the app is still in the recent menu
  4. Bring the app back to the foreground, i.e., come to react app again
  5. Tap the “+” icon to start a second call, and wait for the video of yourself
  6. End the second call
  7. Move the app to the background, and try to open another app while the call is in progress, and make sure the app is still in the recent menu
  8. Bring the app back to the foreground

Expected Behaviour

After calling the room.disconnect(), and stopping/unpublishing all tracks:

  • All audio and video streams should be fully released
  • iOS should not show microphone or camera usage indicators
  • No active media session should remain

Actual Behaviour

  • iOS continues to show the microphone and/or camera usage indicator at the top of the screen
  • Indicates that audio/video streams are still alive
  • This happens even though:
    • room.disconnect() is called
    • Tracks are unpublished and stopped
    • No active room reference exists

Additional Notes

  • Issue occurs only on iOS
  • Android behaves as expected
  • Reproducible when:
    • Accepting a second call
    • After background → foreground transitions
  • All local tracks are explicitly stopped and removed from publications

Attempted Workarounds / Reproduction Scenarios
We attempted multiple approaches to ensure that the previous audio/video streams are fully stopped before starting a second call. The following scenarios were tested, but the issue persists.

  1. Steps to reproduce Audio / Video Stream Stuck

    1. Run the app on a real iOS device
    2. Start the first video/audio call
    3. Move the app to the background, i.e., try to open another app while the call is in progress, and make sure the app is still in the recent menu
    4. Bring the app back to the foreground, i.e., come to react app again
    5. Tap the “+” icon to start a second call, and wait for the video of yourself
    6. End the second call
    7. Move the app to the background, and try to open another app while the call is in progress, and make sure the app is still in the recent menu
    8. Bring the app back to the foreground
  2. Hard Reload the Component Route
    Scenario 1
    1. Accept the second incoming call
    2. Decline the previous call
    3. Perform a hard reload of the video component route

    Scenario 2
    1. Accept the second incoming call
    2. Wait ~10 seconds to allow reconnection of the first call
    3. Decline the first call
    4. Start the second call with a hard reload of the component route

  3. Restart Audio / Video Tracks
    1. Accept the second incoming call
    2. Decline the previous call
    3. Start the second call
    4. Explicitly stop and restart audio and video tracks

Result
Despite the above steps:

  1. Audio and/or video streams from the previous call remain active
  2. room.disconnect() and track cleanup do not fully release media resources
  3. The issue consistently reproduces when handling consecutive calls

Question

Is this a known issue with twilio-video.js on iOS WKWebView, or is there a recommended approach to fully release media streams when handling consecutive calls?

Any guidance or fix would be greatly appreciated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions