You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP β†’
Socket
Book a DemoInstallSign in
Socket

react-native-audio-recorder-player

Package Overview
Dependencies
Maintainers
1
Versions
138
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-native-audio-recorder-player

React Native Audio Recorder and Player.

4.2.0
latest
Source
npmnpm
Version published
Weekly downloads
41K
3.2%
Maintainers
1
Weekly downloads
Β 
Created
Source

react-native-audio-recorder-player

yarn Version Downloads CI publish-package License code style: prettier LICENSE

Platform - iOS Platform - Android Platform - Web

πŸŽ‰ Version 4.1.0 Released with NitroModule Support!

⚠️ Important: Version 4.0.0 had issues with Nitro integration. Please install version 4.1.0 or later.

πŸ”΄ Critical for v4.x: Recording operations now run in background threads. You MUST implement loading states to handle the async delays, or your UI may appear unresponsive. See Component Examples for proper implementation.

This is a high-performance React Native module for audio recording and playback, now powered by NitroModules for direct native module access without bridge overhead. The library provides simple recorder and player functionalities for iOS, Android, and Web platforms with full TypeScript support and type safety.

Preview

Documentation & Resources

What's New in 4.0.0 πŸš€

NitroModule Migration

Version 4.0.0 introduces a complete rewrite using NitroModules, offering:

  • Zero Bridge Overhead: Direct native module access for maximum performance
  • Full Type Safety: TypeScript definitions generated from native specs
  • Synchronous Methods: Where appropriate, for better developer experience
  • Event Listeners: Native callbacks with type-safe event payloads
  • Cross-Platform Code Generation: Automatic code generation for iOS (Swift) and Android (Kotlin)
  • Background Processing: Recording operations now run in background threads to prevent UI blocking, requiring loading state management
  • Web Platform Support: Full support for web browsers using Web Audio API and MediaRecorder API

Requirements

  • React Native >= 0.73.0
  • iOS >= 13.0
  • Android minSdk >= 24
  • Expo SDK >= 50 (for Expo users)

Migration from Older Versions

If you're upgrading from version 3.x or earlier, please refer to our Migration Guide for detailed instructions and breaking changes.

Getting started

⚠️ Important: Install version 4.1.0 or later to avoid Nitro integration issues from version 4.0.0.

  • Install packages:

    yarn add react-native-audio-recorder-player react-native-nitro-modules
    

    Or using npm:

    npm install react-native-audio-recorder-player react-native-nitro-modules
    

Post Installation

After installing the packages, follow these steps:

  • iOS Setup:

    cd ios && pod install
    
  • Android Setup: No additional steps required. The module uses autolinking.

  • Web Setup: For React Native Web, install the additional dependency:

    yarn add react-native-web
    

    Then configure your webpack to include the web-specific implementation:

    // webpack.config.js
    module.exports = {
      resolve: {
        alias: {
          'react-native': 'react-native-web'
        }
      }
    };
    

Note: The nitro-codegen command is already run during the library's build process. You don't need to run it in your application.

Platform-specific Configuration

iOS Configuration

  • Microphone Permission: Add to your Info.plist:

    <key>NSMicrophoneUsageDescription</key>
    <string>Give $(PRODUCT_NAME) permission to use your microphone. Your record wont be shared without your permission.</string>
    
  • Minimum iOS Version: Ensure your minimum deployment target is iOS 13.0 or higher in your Podfile:

    platform :ios, '13.0'
    

Android Configuration

On Android you need to add permissions to AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Also, android above Marshmallow needs runtime permission to record audio. Below are two approaches:

Minimal Approach (Recommended for Android 13+):

if (Platform.OS === 'android') {
  try {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
      {
        title: 'Audio Recording Permission',
        message: 'This app needs access to your microphone to record audio.',
        buttonNeutral: 'Ask Me Later',
        buttonNegative: 'Cancel',
        buttonPositive: 'OK',
      }
    );
    
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      console.log('Recording permission granted');
    } else {
      console.log('Recording permission denied');
      return;
    }
  } catch (err) {
    console.warn(err);
    return;
  }
}

Full Permissions Approach (For older Android versions):

if (Platform.OS === 'android') {
  try {
    const grants = await PermissionsAndroid.requestMultiple([
      PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
      PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
      PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
    ]);

    if (
      grants['android.permission.WRITE_EXTERNAL_STORAGE'] ===
        PermissionsAndroid.RESULTS.GRANTED &&
      grants['android.permission.READ_EXTERNAL_STORAGE'] ===
        PermissionsAndroid.RESULTS.GRANTED &&
      grants['android.permission.RECORD_AUDIO'] ===
        PermissionsAndroid.RESULTS.GRANTED
    ) {
      console.log('All permissions granted');
    } else {
      console.log('All required permissions not granted');
      return;
    }
  } catch (err) {
    console.warn(err);
    return;
  }
}

Methods

MethodParamReturnDescription
mmssnumber secondsstringConvert seconds to minute:second string
mmssssnumber secondsstringConvert seconds to minute:second:millisecond string
setSubscriptionDurationnumber durationvoidSet callback interval in ms (default 500ms)
startRecorderstring? uri, AudioSet? audioSet,Promise<string>Start recording with optional path and audio settings
boolean? meteringEnabled
pauseRecorderPromise<string>Pause recording
resumeRecorderPromise<string>Resume recording
stopRecorderPromise<string>Stop recording and return file path
startPlayerstring? uri, Record<string, string>? headersPromise<string>Start playback with optional URI and HTTP headers
stopPlayerPromise<string>Stop playback
pausePlayerPromise<string>Pause playback
resumePlayerPromise<string>Resume playback
seekToPlayernumber millisecondsPromise<string>Seek to position in milliseconds
setVolumenumber valuePromise<string>Set volume (0.0 - 1.0)
setPlaybackSpeednumber speedPromise<string>Set playback speed (0.5 - 2.0)
addRecordBackListenerFunction callbackvoidAdd recording progress listener
removeRecordBackListenervoidRemove recording progress listener
addPlayBackListenerFunction callbackvoidAdd playback progress listener
removePlayBackListenervoidRemove playback progress listener
addPlaybackEndListenerFunction callbackvoidAdd playback completion listener
removePlaybackEndListenervoidRemove playback completion listener

Usage

Basic Usage

import AudioRecorderPlayer, {
  AudioEncoderAndroidType,
  AudioSourceAndroidType,
  AVEncoderAudioQualityIOSType,
  AVEncodingOption,
  RecordBackType,
  PlayBackType,
} from 'react-native-audio-recorder-player';

// AudioRecorderPlayer is a singleton instance, use directly

// Recording
const onStartRecord = async () => {
  // Set up recording progress listener
  AudioRecorderPlayer.addRecordBackListener((e: RecordBackType) => {
    console.log('Recording progress:', e.currentPosition, e.currentMetering);
    setRecordSecs(e.currentPosition);
    setRecordTime(AudioRecorderPlayer.mmssss(Math.floor(e.currentPosition)));
  });

  const result = await AudioRecorderPlayer.startRecorder();
  console.log('Recording started:', result);
};

const onStopRecord = async () => {
  const result = await AudioRecorderPlayer.stopRecorder();
  AudioRecorderPlayer.removeRecordBackListener();
  console.log('Recording stopped:', result);
};

// Pause/Resume Recording
const onPauseRecord = async () => {
  await AudioRecorderPlayer.pauseRecorder();
  console.log('Recording paused');
};

const onResumeRecord = async () => {
  await AudioRecorderPlayer.resumeRecorder();
  console.log('Recording resumed');
};

// Playback
const onStartPlay = async () => {
  // Set up playback progress listener
  AudioRecorderPlayer.addPlayBackListener((e: PlayBackType) => {
    console.log('Playback progress:', e.currentPosition, e.duration);
    setCurrentPosition(e.currentPosition);
    setTotalDuration(e.duration);
    setPlayTime(AudioRecorderPlayer.mmssss(Math.floor(e.currentPosition)));
    setDuration(AudioRecorderPlayer.mmssss(Math.floor(e.duration)));
  });

  // Set up playback end listener
  AudioRecorderPlayer.addPlaybackEndListener((e: PlaybackEndType) => {
    console.log('Playback completed:', e);
    // Handle playback completion
    setIsPlaying(false);
    setCurrentPosition(0);
  });

  const result = await AudioRecorderPlayer.startPlayer();
  console.log('Playback started:', result);
};

const onPausePlay = async () => {
  await AudioRecorderPlayer.pausePlayer();
};

const onStopPlay = async () => {
  AudioRecorderPlayer.stopPlayer();
  AudioRecorderPlayer.removePlayBackListener();
  AudioRecorderPlayer.removePlaybackEndListener();
};

// Seeking
const seekTo = async (milliseconds: number) => {
  await AudioRecorderPlayer.seekToPlayer(milliseconds);
};

// Volume control
const setVolume = async (volume: number) => {
  await AudioRecorderPlayer.setVolume(volume); // 0.0 - 1.0
};

// Speed control
const setSpeed = async (speed: number) => {
  await AudioRecorderPlayer.setPlaybackSpeed(speed); // 0.5 - 2.0
};

Audio Configuration

const audioSet: AudioSet = {
  // iOS Settings
  AVSampleRateKeyIOS: 44100,
  AVFormatIDKeyIOS: AVEncodingOption.aac,
  AVEncoderAudioQualityKeyIOS: AVEncoderAudioQualityIOSType.high,
  AVNumberOfChannelsKeyIOS: 2,

  // Android Settings
  AudioEncoderAndroid: AudioEncoderAndroidType.AAC,
  AudioSourceAndroid: AudioSourceAndroidType.MIC,
};

const meteringEnabled = true; // Enable audio metering

const uri = await AudioRecorderPlayer.startRecorder(
  undefined, // Use default path
  audioSet,
  meteringEnabled
);

Default Path

  • Default path for android uri is {cacheDir}/sound.mp4.
  • Default path for ios uri is {cacheDir}/sound.m4a.
  • Default path for web: Files are stored as Blob URLs in memory.

Tip: Store the file path returned by startRecorder() immediately for later use in playback or file management.

Web Platform Support

Features

  • Audio recording using MediaRecorder API
  • Audio playback using Web Audio API
  • Support for common audio formats (depends on browser)
  • Real-time playback progress updates
  • Volume and speed control

Limitations

  • Recording format is browser-dependent (typically webm/opus)
  • Some audio configuration options are not supported
  • File paths are Blob URLs instead of file system paths
  • Metering during recording is not currently supported

Browser Compatibility

  • Chrome/Edge: Full support
  • Firefox: Full support
  • Safari: Limited recording format support (may require polyfills)

Component-Based Implementation

For better code organization, consider separating recording and playback into separate components:

Important: Loading States

Note: Starting from version 4.x, recording operations (start/stop) are processed in the background to prevent UI blocking. This means there's a slight delay between calling the method and the actual operation completing. We strongly recommend implementing loading states to provide better user experience.

AudioRecorder Component with Loading States

import React, { useState } from 'react';
import { View, Button, Text, ActivityIndicator } from 'react-native';
import AudioRecorderPlayer from 'react-native-audio-recorder-player';

export const AudioRecorder = ({ onRecordingComplete }) => {
  const [isRecording, setIsRecording] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [recordTime, setRecordTime] = useState('00:00:00');

  const onStartRecord = async () => {
    setIsLoading(true);
    try {
      const result = await AudioRecorderPlayer.startRecorder();
      AudioRecorderPlayer.addRecordBackListener((e) => {
        setRecordTime(AudioRecorderPlayer.mmssss(Math.floor(e.currentPosition)));
      });
      setIsRecording(true);
    } catch (error) {
      console.error('Failed to start recording:', error);
    } finally {
      setIsLoading(false);
    }
  };

  const onStopRecord = async () => {
    setIsLoading(true);
    try {
      const result = await AudioRecorderPlayer.stopRecorder();
      AudioRecorderPlayer.removeRecordBackListener();
      setIsRecording(false);
      onRecordingComplete?.(result);
    } catch (error) {
      console.error('Failed to stop recording:', error);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <View>
      <Text>{recordTime}</Text>
      <Button
        title={isRecording ? 'Stop Recording' : 'Start Recording'}
        onPress={isRecording ? onStopRecord : onStartRecord}
        disabled={isLoading}
      />
      {isLoading && <ActivityIndicator />}
    </View>
  );
};

AudioPlayer Component with Loading States

import React, { useState } from 'react';
import { View, Button, Text, ActivityIndicator } from 'react-native';
import AudioRecorderPlayer from 'react-native-audio-recorder-player';

export const AudioPlayer = ({ audioPath }) => {
  const [isPlaying, setIsPlaying] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [playTime, setPlayTime] = useState('00:00:00');
  const [duration, setDuration] = useState('00:00:00');

  const onStartPlay = async () => {
    setIsLoading(true);
    try {
      const msg = await AudioRecorderPlayer.startPlayer(audioPath);
      AudioRecorderPlayer.addPlayBackListener((e) => {
        setPlayTime(AudioRecorderPlayer.mmssss(Math.floor(e.currentPosition)));
        setDuration(AudioRecorderPlayer.mmssss(Math.floor(e.duration)));
      });
      
      // Use the proper playback end listener
      AudioRecorderPlayer.addPlaybackEndListener((e) => {
        console.log('Playback completed', e);
        setIsPlaying(false);
        setPlayTime('00:00:00');
      });
      
      setIsPlaying(true);
    } catch (error) {
      console.error('Failed to start playback:', error);
    } finally {
      setIsLoading(false);
    }
  };

  const onStopPlay = async () => {
    setIsLoading(true);
    try {
      await AudioRecorderPlayer.stopPlayer();
      AudioRecorderPlayer.removePlayBackListener();
      AudioRecorderPlayer.removePlaybackEndListener();
      setIsPlaying(false);
      setPlayTime('00:00:00');
      setDuration('00:00:00');
    } catch (error) {
      console.error('Failed to stop playback:', error);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <View>
      <Text>{playTime} / {duration}</Text>
      <Button
        title={isPlaying ? 'Stop' : 'Play'}
        onPress={isPlaying ? onStopPlay : onStartPlay}
        disabled={!audioPath || isLoading}
      />
      {isLoading && <ActivityIndicator />}
    </View>
  );
};

Example App

Running the Example

  • Navigate to the example directory:

    cd example
    
  • Install dependencies:

    yarn install
    
  • Start the development server:

    yarn start
    
  • Run on your platform:

    # iOS
    yarn ios
    
    # Android
    yarn android
    

Troubleshooting

iOS Recording Error: "Unknown std::runtime_error"

If you encounter this error when trying to record on iOS:

  • Ensure microphone permissions are properly configured in your Info.plist:

    <key>NSMicrophoneUsageDescription</key>
    <string>Your app needs microphone access to record audio</string>
    
  • Clean and rebuild your iOS project:

    cd ios
    rm -rf build Pods
    pod install
    cd ..
    yarn ios
    
  • Make sure you're testing on a real device if using the simulator doesn't work. Some audio features require real hardware.

  • Verify the Nitro modules are properly linked by checking that the [NitroModules] πŸ”₯ AudioRecorderPlayer is boosted by nitro! message appears during pod install.

Common Issues

  • "nitro-codegen" command not found: This command is only needed when developing the library itself, not when using it in your app.
  • Module not found errors: Make sure to run pod install after installing the package.
  • Android build issues: Ensure your minSdkVersion is 24 or higher in android/build.gradle.

Clean Build Instructions

If you're experiencing build issues or runtime errors after updating the library:

iOS Clean Build

cd ios
rm -rf ~/Library/Caches/CocoaPods
rm -rf Pods
rm -rf ~/Library/Developer/Xcode/DerivedData/*
pod cache clean --all
pod install
cd ..

Then in Xcode:

  • Product β†’ Clean Build Folder (β‡§βŒ˜K)
  • Product β†’ Build (⌘B)

Android Clean Build

cd android
./gradlew clean
rm -rf ~/.gradle/caches/
cd ..

Then rebuild:

yarn android
# or
npx react-native run-android

Both Platforms

You can also try resetting Metro cache:

npx react-native start --reset-cache

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

Made with create-react-native-library

Keywords

react-native

FAQs

Package last updated on 20 Jul 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts