๐ Cross-platform audio playback for React Native โ Play sound clips on iOS and Android with full TypeScript support and modern React Native architecture compatibility.
๐ Note: This library focuses on audio clips playback, not streaming. For streaming audio, consider react-native-video or other dedicated streaming solutions.
iOS Implementation: Uses AVAudioPlayer for optimal performance and compatibility.
Android Implementation: Uses MediaPlayer with proper audio focus handling.
| Feature | iOS | Android | | ---------------------------- | --- | ------- | | Loading | | Load from app bundle | โ | โ | | Load from local files | โ | โ | | Load from network URLs | โ | โ | | Playback | | Play/Pause/Stop | โ | โ | | Playback completion callback | โ | โ | | Resume playback | โ | โ | | Reset to beginning | โ | โ | | Audio Control | | Volume control | โ | โ | | Pan (L/R stereo) | โ | โ | | Playback speed | โ | โ | | System Integration | | Get system volume | โ | โ | | Set system volume | โ | โ | | Advanced Features | | Loop control | โ | โ | | Exact loop count | โ | โ | | Seek to time position | โ | โ | | Get current position | โ | โ | | Get duration | โ | โ | | Get channel count | โ | โ | | Resource Management | | Explicit resource cleanup | โ | โ |
npm install react-native-sound
yarn add react-native-sound
This library supports both the old and new React Native architecture:
undefined is not an object (evaluating 'RNSound.IsAndroid')This usually indicates a linking issue. Try:
Clear build cache:
cd android && ./gradlew cleanBuildCache
Reset Metro cache:
npx react-native start --reset-cache
Clean and rebuild:
# iOS
cd ios && rm -rf build && cd .. && npx react-native run-ios
# Android
cd android && ./gradlew clean && cd .. && npx react-native run-android
android/app/src/main/res/raw/Check out our enhanced example app with both remote and local audio playback:
/example - Full-featured demo applicationSave audio files in android/app/src/main/res/raw/:
android/app/src/main/res/raw/
โโโ whoosh.mp3 โ
Correct
โโโ button_click.wav โ
Correct
โโโ my-sound.mp3 โ Use underscores: my_sound.mp3
Note: Use lowercase, underscored filenames. No subdirectories allowed.
import Sound from "react-native-sound";
// Enable playback in silence mode (important for iOS)
Sound.setCategory("Playback");
// Load a sound file from the app bundle
const whoosh = new Sound("whoosh.mp3", Sound.MAIN_BUNDLE, (error) => {
if (error) {
console.log("Failed to load the sound", error);
return;
}
// Sound loaded successfully
console.log("Duration:", whoosh.getDuration(), "seconds");
console.log("Channels:", whoosh.getNumberOfChannels());
// Play the sound
whoosh.play((success) => {
if (success) {
console.log("Successfully finished playing");
} else {
console.log("Playback failed due to audio decoding errors");
}
});
});
// Audio controls
whoosh.setVolume(0.5); // 50% volume
whoosh.setPan(1); // Full right stereo
whoosh.setNumberOfLoops(-1); // Loop indefinitely
// Get current properties
console.log("Volume:", whoosh.getVolume());
console.log("Pan:", whoosh.getPan());
console.log("Loops:", whoosh.getNumberOfLoops());
// Seek to specific time
whoosh.setCurrentTime(2.5);
// Get current playback position
whoosh.getCurrentTime((seconds) => {
console.log("Current time:", seconds);
});
// Control playback
whoosh.pause(); // Pause playback
whoosh.stop(() => {
// Stop and rewind
whoosh.play(); // Play from beginning
});
// Always release resources when done
whoosh.release();
// From app bundle (most common)
const bundleSound = new Sound("sound.mp3", Sound.MAIN_BUNDLE, callback);
// From documents directory
const docSound = new Sound("sound.mp3", Sound.DOCUMENT, callback);
// From library directory
const libSound = new Sound("sound.mp3", Sound.LIBRARY, callback);
// From absolute path
const pathSound = new Sound("/path/to/sound.mp3", "", callback);
// From remote URL (iOS/Android only)
const urlSound = new Sound("https://example.com/sound.mp3", "", callback);
import { useEffect, useRef, useState } from "react";
import Sound from "react-native-sound";
const useSound = (filename: string) => {
const sound = useRef<Sound | null>(null);
const [isLoaded, setIsLoaded] = useState(false);
const [isPlaying, setIsPlaying] = useState(false);
useEffect(() => {
sound.current = new Sound(filename, Sound.MAIN_BUNDLE, (error) => {
if (error) {
console.log("Error loading sound:", error);
return;
}
setIsLoaded(true);
});
return () => {
sound.current?.release();
};
}, [filename]);
const play = () => {
if (sound.current && isLoaded) {
sound.current.play((success) => {
setIsPlaying(false);
});
setIsPlaying(true);
}
};
const stop = () => {
if (sound.current) {
sound.current.stop();
setIsPlaying(false);
}
};
return { play, stop, isLoaded, isPlaying };
};
play()AVAudioSessionCategoryAmbient to mix multiple soundsSupports: AAC, AIFF, CAF, MP3, WAV, and more
Supports: 3GPP, MP4, MP3, AAC, OGG, FLAC, WAV, and more
/sdcard/ prefix (e.g., /sdcard/Downloads/sound.mp3)sound.setVolume(0.5).setPan(0.5).play())| Library | Purpose | Best For | | -------------------------------------------------------------------------------------------------------- | ----------------------- | ---------------------------- | | react-native-video | Video & audio streaming | Streaming audio/video | | react-native-audio-toolkit | Advanced audio features | Recording & complex audio | | Expo Audio | Expo audio solution | Expo managed workflow | | @react-native-async-storage/async-storage | Storage | Persisting audio preferences |
We welcome contributions! Here's how you can help:
npm installcd example && npm install && npm run androidFollow existing TypeScript/JavaScript patterns
Use meaningful commit messages
Keep changes focused and atomic
To minimize playback delay, you may want to preload a sound file without calling play() (e.g. var s = new Sound(...);) during app initialization. This also helps avoid a race condition where play() may be called before loading of the sound is complete, which results in no sound but no error because loading is still being processed.
You can play multiple sound files at the same time. Under the hood, this module uses AVAudioSessionCategoryAmbient to mix sounds on iOS.
You may reuse a Sound instance for multiple playbacks.
On iOS, the module wraps AVAudioPlayer that supports aac, aiff, mp3, wav etc. The full list of supported formats can be found at https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/CoreAudioOverview/SupportedAudioFormatsMacOSX/SupportedAudioFormatsMacOSX.html
On Android, the module wraps android.media.MediaPlayer. The full list of supported formats can be found at https://developer.android.com/guide/topics/media/media-formats.html
On Android, the absolute path can start with '/sdcard/'. So, if you want to access a sound called "my_sound.mp3" on Downloads folder, the absolute path will be: '/sdcard/Downloads/my_sound.mp3'.
You may chain non-getter calls, for example, sound.setVolume(.5).setPan(.5).play().
MIT License - see LICENSE file for details.
If this library helps your project, consider:
Made with โค๏ธ by the React Native community