@sekizlipenguen/react-native-simple-sound-player
v1.0.5
Published
A simple React Native sound player for MP3 and other audio files without external dependencies
Maintainers
Readme
@sekizlipenguen/react-native-simple-sound-player
🎵 A lightweight and simple React Native module for playing audio files with intelligent caching
- ✅ Local & Remote Audio: Play both local files and HTTPS URLs
- ✅ Smart Caching: Automatic cache management for remote files
- ✅ Volume Control: Precise volume adjustment (0.0 - 1.0)
- ✅ Loop Support: Infinite or fixed number of loops
- ✅ Event System: Listen to playback completion and errors
- ✅ Options Pattern: Clean API with options object
- ✅ Stop Control: Stop playback at any time
- ✅ TypeScript Ready: Full TypeScript support included
- ✅ Zero Dependencies: No external libraries required
- ✅ Auto Linking: Works out of the box with React Native 0.60+
- ✅ Lightweight: Minimal bundle size, no bloat
- ✅ Simple API: Easy to use, no complex configuration
Installation
Super simple installation - just one command:
npm install @sekizlipenguen/react-native-simple-sound-playeriOS Setup
After installing, run:
npx pod-installAndroid Setup
No additional setup required! The module will automatically link when you build your app.
💡 That's it! No complex configuration, no manual linking, no additional dependencies. Just install and use!
🚀 Quick Start
Get started in seconds with these simple examples:
import SimpleSoundPlayer from '@sekizlipenguen/react-native-simple-sound-player';
// 🎵 Basic Usage - Just one line!
SimpleSoundPlayer.playSound('notification.mp3');
// 🔊 Volume Control - Easy as pie
SimpleSoundPlayer.playSoundWithVolume('music.mp3', 0.8);
// 🌐 Remote URLs - Works instantly
SimpleSoundPlayer.playSound('https://example.com/sound.mp3');
// 💾 Smart Caching - Automatic optimization
SimpleSoundPlayer.playSoundWithVolumeAndCache('https://example.com/music.mp3', 0.5, 3600);
// 🔁 Loop Support - Infinite or fixed loops
SimpleSoundPlayer.playSoundWithVolumeAndCacheAndLoop('ambient.mp3', 0.5, 3600, -1); // -1 = infinite
// 🛑 Stop Playback - Stop currently playing sound
await SimpleSoundPlayer.stop();
// 🎯 Options Pattern - Clean and flexible API
SimpleSoundPlayer.play({
fileName: 'notification.mp3',
volume: 0.8,
loopCount: 3, // Play 3 times
onComplete: () => console.log('Done!'),
onError: (error) => console.error('Error:', error)
});🎯 No complex setup, no configuration files, no learning curve! Just import and play.
📱 Usage Examples
Local Files
// Simple notification sound
await SimpleSoundPlayer.playSound('notification.mp3');
// Background music with low volume
await SimpleSoundPlayer.playSoundWithVolume('background.mp3', 0.3);Remote URLs
// Direct streaming (no cache)
await SimpleSoundPlayer.playSound('https://cdn.example.com/sound.mp3');
// With caching for better performance
await SimpleSoundPlayer.playSoundWithVolumeAndCache(
'https://cdn.example.com/music.mp3',
0.7,
7200 // 2 hours cache
);Cache Duration Examples
// 30 minutes cache
await SimpleSoundPlayer.playSoundWithVolumeAndCache(url, 0.5, 1800);
// 1 hour cache
await SimpleSoundPlayer.playSoundWithVolumeAndCache(url, 0.5, 3600);
// 1 day cache
await SimpleSoundPlayer.playSoundWithVolumeAndCache(url, 0.5, 86400);Loop Examples
// Infinite loop (ambient background music)
await SimpleSoundPlayer.playSoundWithVolumeAndCacheAndLoop('ambient.mp3', 0.5, 3600, -1);
// Play once (default behavior)
await SimpleSoundPlayer.playSoundWithVolumeAndCacheAndLoop('notification.mp3', 0.8, 3600, 0);
// Play 3 times
await SimpleSoundPlayer.playSoundWithVolumeAndCacheAndLoop('alarm.mp3', 1.0, 3600, 3);
// Using options pattern
await SimpleSoundPlayer.play({
fileName: 'background.mp3',
volume: 0.3,
loopCount: -1, // -1 = infinite, 0 = once, >0 = number of times
});Event System Examples
// Using callbacks in options object
await SimpleSoundPlayer.play({
fileName: 'notification.mp3',
onComplete: (event) => {
console.log('Sound completed:', event);
},
onError: (event) => {
console.error('Error occurred:', event);
}
});
// Using global event listeners
const subscription = SimpleSoundPlayer.addEventListener('onSoundComplete', (event) => {
console.log('Any sound completed:', event);
});
// Remove listener when done
SimpleSoundPlayer.removeEventListener(subscription);Complete Example with Events and Stop
import React, {useEffect} from 'react';
import {Button, View, Alert} from 'react-native';
import {useNavigation, useFocusEffect} from '@react-navigation/native';
import SimpleSoundPlayer from '@sekizlipenguen/react-native-simple-sound-player';
const App = () => {
const navigation = useNavigation();
useEffect(() => {
// Global event listener
const subscription = SimpleSoundPlayer.addEventListener('onSoundComplete', (event) => {
console.log('Sound completed:', event);
});
return () => {
SimpleSoundPlayer.removeEventListener(subscription);
// Stop sound when component unmounts
SimpleSoundPlayer.stop();
};
}, []);
// Stop sound when screen loses focus
useFocusEffect(
React.useCallback(() => {
return () => {
// Stop sound when navigating away
SimpleSoundPlayer.stop();
};
}, [])
);
const handlePlayWithCallback = async () => {
try {
await SimpleSoundPlayer.play({
fileName: 'notification.mp3',
volume: 0.8,
loopCount: 0, // Play once
onComplete: () => {
Alert.alert('Success', 'Sound played successfully!');
},
onError: (error) => {
Alert.alert('Error', error.error || 'Unknown error');
}
});
} catch (error) {
Alert.alert('Error', error.message);
}
};
const handlePlayAmbient = async () => {
try {
await SimpleSoundPlayer.play({
fileName: 'ambient.mp3',
volume: 0.3,
loopCount: -1, // Infinite loop
onError: (error) => {
Alert.alert('Error', error.error || 'Unknown error');
}
});
} catch (error) {
Alert.alert('Error', error.message);
}
};
const handleStop = async () => {
try {
await SimpleSoundPlayer.stop();
Alert.alert('Success', 'Sound stopped');
} catch (error) {
Alert.alert('Error', error.message);
}
};
const handleGoBack = async () => {
await SimpleSoundPlayer.stop();
navigation.goBack();
};
return (
<View style={{flex: 1, justifyContent: 'center', padding: 20}}>
<Button title="Play Notification" onPress={handlePlayWithCallback} />
<View style={{height: 20}} />
<Button title="Play Ambient (Infinite)" onPress={handlePlayAmbient} />
<View style={{height: 20}} />
<Button title="Stop Sound" onPress={handleStop} />
<View style={{height: 20}} />
<Button title="Go Back (Stop & Exit)" onPress={handleGoBack} />
</View>
);
};
export default App;Complete Example
import React, {useState} from 'react';
import {Button, View, Alert, Text, StyleSheet} from 'react-native';
import SimpleSoundPlayer from '@sekizlipenguen/react-native-simple-sound-player';
const App = () => {
const [isPlaying, setIsPlaying] = useState(false);
const handlePlayLocalSound = async () => {
try {
setIsPlaying(true);
const result = await SimpleSoundPlayer.playSoundWithVolume('notification.mp3', 0.8);
console.log('Local sound played:', result);
Alert.alert('Success', 'Local sound played successfully!');
} catch (error) {
Alert.alert('Error', 'Failed to play local sound: ' + error.message);
} finally {
setIsPlaying(false);
}
};
const handlePlayRemoteSound = async () => {
try {
setIsPlaying(true);
const result = await SimpleSoundPlayer.playSoundWithVolumeAndCache(
'https://cdn.pixabay.com/download/audio/2022/03/22/audio_e350ea2393.mp3',
0.5,
3600 // 1 hour cache
);
console.log('Remote sound played:', result);
Alert.alert('Success', 'Remote sound played successfully!');
} catch (error) {
Alert.alert('Error', 'Failed to play remote sound: ' + error.message);
} finally {
setIsPlaying(false);
}
};
return (
<View style={styles.container}>
<Text style={styles.title}>🎵 Simple Sound Player</Text>
<Button
title={isPlaying ? "Playing..." : "Play Local Sound"}
onPress={handlePlayLocalSound}
disabled={isPlaying}
/>
<View style={styles.spacer} />
<Button
title={isPlaying ? "Playing..." : "Play Remote Sound (Cached)"}
onPress={handlePlayRemoteSound}
disabled={isPlaying}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 30,
},
spacer: {
height: 20,
},
});
export default App;💾 Cache System
The module includes an intelligent caching system for remote audio files:
How It Works
- First Play: Downloads and caches the file locally
- Subsequent Plays: Uses cached file for instant playback
- Auto Cleanup: Removes expired cache files automatically
- Storage: Uses platform-specific cache directories
Cache Locations
- iOS:
~/Library/Caches/SimpleSoundPlayer/ - Android:
/data/data/[package]/cache/SimpleSoundPlayer/
Benefits
- ⚡ Faster Playback: No network delay on cached files
- 📱 Offline Support: Cached files work without internet
- 💰 Data Savings: Reduces bandwidth usage
- 🔄 Auto Management: No manual cache cleanup needed
Adding Sound Files
iOS
- Open your iOS project in Xcode
- Click on your project name in the Project Navigator (top-level folder)
- Right-click and select "Add Files to [YourProjectName]"
- Select your sound files and click "Add"
- Make sure "Add to target" is checked for your main app target
Important: Click on the project name (top-level folder), not subfolders!
Android
- Navigate to
android/app/src/main/res/ - Create a folder named
rawif it doesn't exist - Copy your sound files into the
rawfolder
File Requirements
File Names
- iOS: Simple names without spaces (e.g.,
sound.mp3,notification.wav) - Android: Lowercase letters, numbers, and underscores only (e.g.,
sound.mp3,notification_sound.wav)
Supported Formats
- MP3, WAV, OGG, AAC - Full support
- File size: Keep under 5MB for better performance
📚 API Reference
playSound(fileName)
Plays a sound file with default volume (0.5).
Parameters:
fileName(string): Name of the sound file or URL (supports both local files and remote URLs)
Returns: Promise<{success: boolean, fileName: string, volume: number}>
Example:
const result = await SimpleSoundPlayer.playSound('notification.mp3');
// {success: true, fileName: 'notification.mp3', volume: 0.5}playSoundWithVolume(fileName, volume)
Plays a sound file with custom volume.
Parameters:
fileName(string): Name of the sound file or URL (supports both local files and remote URLs)volume(number): Volume level (0.0 - 1.0)
Returns: Promise<{success: boolean, fileName: string, volume: number}>
Example:
const result = await SimpleSoundPlayer.playSoundWithVolume('music.mp3', 0.8);
// {success: true, fileName: 'music.mp3', volume: 0.8}playSoundWithVolumeAndCache(fileName, volume, cacheDurationSeconds)
Plays a remote sound file with custom volume and intelligent caching.
Parameters:
fileName(string): URL of the remote sound filevolume(number): Volume level (0.0 - 1.0)cacheDurationSeconds(number): Cache duration in seconds (e.g., 3600 for 1 hour)
Returns: Promise<{success: boolean, fileName: string, volume: number}>
Example:
const result = await SimpleSoundPlayer.playSoundWithVolumeAndCache(
'https://example.com/music.mp3',
0.5,
3600
);
// {success: true, fileName: 'https://example.com/music.mp3', volume: 0.5}playSoundWithVolumeAndCacheAndLoop(fileName, volume, cacheDurationSeconds, loopCount)
Plays a sound file with custom volume, caching, and loop support.
Parameters:
fileName(string): Name of the sound file or URLvolume(number): Volume level (0.0 - 1.0)cacheDurationSeconds(number): Cache duration in seconds (e.g., 3600 for 1 hour)loopCount(number):-1: Infinite loop0: Play once (default)>0: Play the specified number of times (e.g.,3plays 3 times)
Returns: Promise<{success: boolean, fileName: string, volume: number}>
Example:
// Infinite loop
const result = await SimpleSoundPlayer.playSoundWithVolumeAndCacheAndLoop(
'ambient.mp3',
0.5,
3600,
-1
);
// Play 3 times
const result = await SimpleSoundPlayer.playSoundWithVolumeAndCacheAndLoop(
'alarm.mp3',
1.0,
3600,
3
);play(options) ⭐ Recommended
Plays a sound file using an options object. This is the recommended way to use the library as it provides a clean and flexible API.
Parameters:
options(object):fileName(string, required): Name of the sound file or URLvolume(number, optional): Volume level (0.0 - 1.0), default:0.5cacheDurationSeconds(number, optional): Cache duration in seconds, default:3600loopCount(number, optional):-1: Infinite loop0: Play once (default)>0: Play the specified number of times
onComplete(function, optional): Callback when sound completes- Receives
event: {success: boolean}
- Receives
onError(function, optional): Callback when an error occurs- Receives
event: {error: string, code?: number}
- Receives
Returns: Promise<{success: boolean, fileName: string, volume: number}>
Example:
// Simple usage
await SimpleSoundPlayer.play({
fileName: 'notification.mp3'
});
// With all options
await SimpleSoundPlayer.play({
fileName: 'ambient.mp3',
volume: 0.3,
cacheDurationSeconds: 7200,
loopCount: -1, // Infinite loop
onComplete: (event) => {
console.log('Sound completed!', event);
},
onError: (event) => {
console.error('Error:', event.error);
}
});
// Play notification 3 times
await SimpleSoundPlayer.play({
fileName: 'notification.mp3',
volume: 0.8,
loopCount: 3,
onComplete: () => {
Alert.alert('Done', 'Notification played 3 times');
}
});addEventListener(eventName, handler)
Adds a global event listener for sound events.
Parameters:
eventName(string): Event name ('onSoundComplete'or'onSoundError')handler(function): Event handler function- For
onSoundComplete: receivesevent: {success: boolean} - For
onSoundError: receivesevent: {error: string, code?: number}
- For
Returns: {remove: () => void} - Subscription object with remove() method
Example:
const subscription = SimpleSoundPlayer.addEventListener('onSoundComplete', (event) => {
console.log('Sound completed:', event);
// {success: true}
});
// Later, remove the listener
subscription.remove();
// or
SimpleSoundPlayer.removeEventListener(subscription);removeEventListener(subscription)
Removes an event listener subscription.
Parameters:
subscription(object): The subscription object returned byaddEventListener
Example:
const subscription = SimpleSoundPlayer.addEventListener('onSoundComplete', handler);
// ... later
SimpleSoundPlayer.removeEventListener(subscription);stop()
Stops the currently playing sound immediately.
Returns: Promise<{success: boolean}>
Example:
// Stop currently playing sound
await SimpleSoundPlayer.stop();
// Stop before navigating away
const handleGoBack = async () => {
await SimpleSoundPlayer.stop();
navigation.goBack();
};
// Stop when component unmounts
useEffect(() => {
return () => {
SimpleSoundPlayer.stop();
};
}, []);Supported Sources
- Local files:
notification.mp3,music.wav,sound.ogg - Remote URLs:
https://example.com/sound.mp3,http://example.com/music.wav - Cached URLs: Automatically cached for specified duration
Error Handling
// Using try-catch
try {
const result = await SimpleSoundPlayer.playSound('nonexistent.mp3');
} catch (error) {
console.log('Error:', error.message);
// Possible errors:
// - "Sound file 'nonexistent.mp3' not found"
// - "Failed to download audio from URL: ..."
// - "Error creating audio player: ..."
}
// Using onError callback (recommended)
await SimpleSoundPlayer.play({
fileName: 'sound.mp3',
onError: (event) => {
console.error('Error:', event.error);
console.error('Error code:', event.code);
}
});
// Using event listener
const subscription = SimpleSoundPlayer.addEventListener('onSoundError', (event) => {
console.error('Error occurred:', event.error);
});Loop Behavior
// Infinite loop (-1): onComplete event is NOT fired (plays forever)
await SimpleSoundPlayer.play({
fileName: 'ambient.mp3',
loopCount: -1,
onComplete: () => {
// This will never be called for infinite loops
}
});
// Play once (0): onComplete event fires when finished
await SimpleSoundPlayer.play({
fileName: 'notification.mp3',
loopCount: 0,
onComplete: () => {
// This will be called when sound finishes
}
});
// Fixed loops (>0): onComplete fires after all loops complete
await SimpleSoundPlayer.play({
fileName: 'alarm.mp3',
loopCount: 3,
onComplete: () => {
// This will be called after 3 plays complete
}
});🔧 Compatibility
Lightweight and compatible with all modern React Native projects:
| Platform | Version | Status |
|----------|---------|--------|
| React Native | >=0.60 | ✅ Fully Supported |
| iOS | 11.0+ | ✅ Fully Supported |
| Android | API 21+ | ✅ Fully Supported |
| TypeScript | 3.0+ | ✅ Fully Supported |
| JavaScript | ES6+ | ✅ Fully Supported |
📦 Bundle Size: ~50KB (minimal footprint) ⚡ Performance: Native implementation, no JavaScript overhead
Features Matrix
| Feature | iOS | Android | Notes | |---------|-----|---------|-------| | Local Files | ✅ | ✅ | Bundle/raw resources | | Remote URLs | ✅ | ✅ | HTTP/HTTPS support | | Volume Control | ✅ | ✅ | 0.0 - 1.0 range | | Caching | ✅ | ✅ | Automatic management | | Loop Support | ✅ | ✅ | Infinite, fixed, or once | | Event System | ✅ | ✅ | Complete and error events | | Stop Control | ✅ | ✅ | Stop playback anytime | | TypeScript | ✅ | ✅ | Full type definitions |
🤝 Contribution
Contributions are welcome! Please feel free to submit a pull request or file an issue in the GitHub repository.
Development Setup
git clone https://github.com/sekizlipenguen/react-native-simple-sound-player.git
cd react-native-simple-sound-player
npm install📄 License
This project is licensed under the MIT License.
🙏 Acknowledgments
- Built with ❤️ by Sekizli Penguen
- Inspired by the React Native community
- Special thanks to all contributors and users
