Implementing Offline Echo-Cancelled Audio Record/Playback in Expo React Native Using react-native-webrtc
1. Introduction: The Challenge of High-Quality Offline Audio in Modern Apps
Mobile applications, including productivity tools, podcasting platforms, and secure communication suites, increasingly require robust audio functionality. Often, end users expect an app to record and play back audio reliably, even without an internet connection. More importantly, in scenarios like note-taking or two-way communication, echo cancellation becomes vital for clear voice quality.
Why Echo Cancellation and Offline Local Capability?
When replayed sound is "heard" by the microphone—such as when recording and playing audio simultaneously or when the user keeps the phone on speaker—echo is introduced. This results in feedback loops, degraded recordings, and a frustrating end-user experience. Echo cancellation is the digital signal processing (DSP) technique that minimizes this problem by subtracting predicted echo from the input.
Equally, offline capability ensures that:
- The app functions without a network connection (crucial for global and field users).
- User privacy and security requirements are satisfied (no cloud uploads).
- Fast, robust performance is maintained on the device itself.
Why Use React Native (Expo) and react-native-webrtc?
- React Native, especially with Expo, enables rapid cross-platform development and access to device APIs.
- react-native-webrtc brings low-level, native audio and video streaming capabilities, exposing fine-grained control over audio inputs, including echo cancellation—crucial for our task.
This blog will walk step-by-step through the best practices, practical configuration, and richly annotated code to build an offline audio application in Expo React Native with echo cancellation, using both built-in features and custom native modules where necessary.
References:
2. Architectural Overview: Expo, Native Modules, and Offline Workflows
Understanding Expo Workflows
Expo offers two major development modes:
- Managed workflow (easy, but limited for low-level modules).
- Bare workflow (full native code and module support).
Note: Echo cancellation and advanced audio recording require direct native access; thus, you must use the Bare workflow or EAS Build with Expo modules that wrap native code such as react-native-webrtc.
react-native-webrtc: Capabilities for Local Audio
Originally designed for real-time communication (VoIP, video call), react-native-webrtc can function entirely offline if no “peer connection” is established. Its power comes from exposing:
- Access to local device microphones and speakers at a low level.
- Media constraints (like
echoCancellation,noiseSuppression, andautoGainControl). - Real-time audio stream processing.
- Direct control over audio streams and ability to save them to disk.
Key Advantages:
- Fine-grained echo cancellation settings.
- Compatibility with both Android and iOS native audio stacks.
- No inherent need for networking in purely local “recorder/player” workflows.
What About expo-av or expo-audio?
- expo-av/expo-audio provide out-of-the-box recording and playback, but do NOT expose echo cancellation and real-time audio buffer manipulation. For most offline recording, they are fine—but if echo management is crucial, you must reach for a module like react-native-webrtc.
- Many third-party audio libraries (such as react-native-realtime-audio) attempt to abstract these advanced flows, but still require native workflow or EAS Build.
Workflow Selection Table:
| Requirement | Expo Managed | EAS Build | Bare Workflow |
|---|---|---|---|
| Basic recording | ✔️ | ✔️ | ✔️ |
| Echo cancellation | ❌ | ✔️ | ✔️ |
| Native buffer access | ❌ | ✔️ | ✔️ |
| Advanced config/control | ❌ | ✔️ | ✔️ |
3. Enabling Echo Cancellation in react-native-webrtc
How Echo Cancellation Works
On both iOS and Android, the WebRTC engine uses system APIs to route microphone input through hardware/OS-level echo cancellers when you request it in constraints.
In react-native-webrtc, this is controlled by passing echoCancellation: true in your media constraints to getUserMedia.
Example Media Constraints:
Js
When passed to getUserMedia, this instructs the engine to request a voice-optimized input from the OS, activating echo suppression on supported devices.
Limitations & Hardware Considerations
- Effectiveness depends on hardware. Modern phones generally do well; older or cheap phones might not.
- Bluetooth headsets often bypass EC hardware. Use speakerphone/mic for best results and document this for end users.
- User permissions are essential. You must request and handle microphone permissions at runtime.
Practical Example: Requesting an Audio Stream with Echo Cancellation
Js
References
4. Full Example: Offline Echo-Cancelled Recorder/Player Workflow in Expo React Native
Step 1: Prerequisites and Setup
Project Initialization
Bash
- Make sure to eject to the Bare workflow if using react-native-webrtc!
- If building via EAS Build, ensure your project is configured for native modules.
Permissions
Set up in app.json (or app.config.js):
Json
Handle runtime permissions in your code using Expo’s Permissions API.
Step 2: Creating the Offline Recorder
Requesting a MediaStream with Echo Cancellation
Js
Recording to a File
WebRTC provides a raw audio stream (MediaStreamTrack). To store audio:
- Direct WebRTC does not have a “MediaRecorder” in React Native; you must use a bridge library such as
react-native-audio-recordor process PCM data withreact-native-fs. - Community tools like react-native-audio-record facilitate capturing PCM/WAV locally in sync with a media stream.
Hybrid Example (simplified):
Js
Step 3: Playback Locally
- Use expo-av or react-native-sound to play back the local file.
Example with expo-av:
Js
Step 4: Full Component Example
Js
This approach ensures recordings are local (offline) and, with proper capture constraints, echo cancellation is active.
5. Troubleshooting and Best Practices
Common Pitfalls
- Permissions not granted: Always handle permission errors gracefully.
- Echo cancellation not effective: Remind users to use phone speakers, not Bluetooth; echo suppression depends on the hardware.
- Expo Managed workflow limitation: Managed workflow cannot link native modules required by react-native-webrtc. Always use EAS Build or eject to Bare.
- Platform bugs: Test on both Android and iOS with real devices, as emulator audio stacks may not reflect reality.
Tips from the Community
- For maximum EC, set all relevant constraints (
echoCancellation,noiseSuppression,autoGainControl). - If advanced local streaming is critical (e.g., visualization), buffer and process PCM data with a worker thread.
- Store files to persistent storage using FileSystem APIs for robust offline replay.
- Test at different volumes and environments to verify echo is adequately suppressed.






