@umituz/react-native-sound
v1.2.7
Published
Universal sound playback and caching library for React Native apps
Downloads
744
Maintainers
Readme
@umituz/react-native-sound
Universal sound playback and caching library for React Native apps. Supports local assets, remote URLs, and automatic caching with a simple, clean API.
Features
- 🎵 Universal Sound Playback - Play sounds from local assets or remote URLs
- 💾 Automatic Caching - Cache remote sounds locally for offline playback
- 🔄 Streaming Support - Stream sounds while downloading in background
- 🎛️ Playback Controls - Play, pause, stop, volume, and rate control
- 🎯 Singleton Pattern - Only one sound plays at a time across the app
- 🔌 Storage Abstraction - Works with any storage provider (Firebase, AWS S3, etc.)
- 📦 Zero Dependencies - Only requires
expo-avandexpo-file-system
Installation
npm install @umituz/react-native-soundPeer Dependencies
npm install expo-av expo-file-systemQuick Start
Basic Usage
import { useSoundPlayback, Sound } from '@umituz/react-native-sound';
function MyComponent() {
const { playSound, stopSound, isPlaying } = useSoundPlayback();
const sound: Sound = {
id: 'ocean-waves',
name: 'Ocean Waves',
filename: 'ocean-waves.mp3',
storageUrl: 'sounds/ocean-waves.mp3', // Or full URL
};
return (
<Button
onPress={() => {
if (isPlaying(sound.id)) {
stopSound();
} else {
playSound(sound);
}
}}
>
{isPlaying(sound.id) ? 'Stop' : 'Play'}
</Button>
);
}With Storage Service (Firebase, AWS S3, etc.)
import { useSoundPlayback, IStorageService } from '@umituz/react-native-sound';
import { getStorage } from 'firebase/storage';
import { ref, getDownloadURL } from 'firebase/storage';
// Implement storage service
class FirebaseStorageService implements IStorageService {
async getDownloadUrl(storagePath: string): Promise<string> {
const storage = getStorage();
const storageRef = ref(storage, storagePath);
return getDownloadURL(storageRef);
}
}
function MyComponent() {
const storageService = new FirebaseStorageService();
const { playSound, stopSound } = useSoundPlayback({
storageService,
});
// ... rest of component
}Local Assets
import { useSoundPlayback, Sound } from '@umituz/react-native-sound';
import oceanWavesSound from './assets/sounds/ocean-waves.mp3';
function MyComponent() {
const { playSound } = useSoundPlayback();
const sound: Sound = {
id: 'ocean-waves',
name: 'Ocean Waves',
localAsset: oceanWavesSound, // Bundled asset
};
return <Button onPress={() => playSound(sound)}>Play</Button>;
}Cache Management
import { useSoundCache } from '@umituz/react-native-sound';
function CacheSettings() {
const {
cacheSize,
clearCache,
isCached,
deleteCachedSound,
} = useSoundCache();
return (
<View>
<Text>Cache Size: {cacheSize.toFixed(2)} MB</Text>
<Button onPress={clearCache}>Clear Cache</Button>
</View>
);
}API Reference
useSoundPlayback(options?)
Main hook for sound playback.
Options
storageService?: IStorageService- Storage service for remote URLsautoConfigureAudioSession?: boolean- Auto-configure audio session (default: true)audioSessionOptions?: {...}- Audio session configuration
Returns
playSound(sound, options?, onProgress?)- Play a soundstopSound()- Stop current soundpauseSound()- Pause current soundresumeSound()- Resume paused soundisPlaying(soundId)- Check if sound is playingplayingSoundId- Currently playing sound IDdownloadingSoundId- Currently downloading sound IDdownloadProgress- Download progress (0-100)isStreaming- Whether sound is streaming
useSoundCache()
Hook for cache management.
Returns
isCached(sound)- Check if sound is cachedgetCachedUri(sound)- Get cached file URIclearCache()- Clear all cachegetCacheSize()- Get cache size in MBdeleteCachedSound(sound)- Delete specific cached soundcacheSize- Current cache size in MBisLoadingCacheSize- Whether cache size is loadingrefreshCacheSize()- Refresh cache size
Sound Entity
interface Sound {
id: string; // Required: Unique identifier
name: string; // Required: Display name
description?: string; // Optional: Description
filename?: string; // Optional: Filename for caching
storageUrl?: string; // Optional: Remote storage path or URL
localAsset?: number; // Optional: Local asset reference
durationSeconds?: number; // Optional: Duration in seconds
isPremium?: boolean; // Optional: Premium flag
category?: string; // Optional: Category
tags?: string[]; // Optional: Tags
metadata?: Record<string, unknown>; // Optional: App-specific metadata
}IStorageService Interface
interface IStorageService {
getDownloadUrl(storagePath: string): Promise<string>;
}Implement this interface for your storage provider (Firebase Storage, AWS S3, etc.).
Architecture
This package follows Domain-Driven Design (DDD) principles:
- Domain Layer: Entities and interfaces
- Infrastructure Layer: Services and storage implementations
- Presentation Layer: React hooks
SOLID Principles
- Single Responsibility: Each service has one clear purpose
- Open/Closed: Extensible through interfaces
- Liskov Substitution: Storage services are interchangeable
- Interface Segregation: Small, focused interfaces
- Dependency Inversion: Depends on abstractions, not concretions
Examples
Multiple Sounds
const sounds: Sound[] = [
{
id: 'ocean',
name: 'Ocean Waves',
filename: 'ocean.mp3',
storageUrl: 'sounds/ocean.mp3',
},
{
id: 'rain',
name: 'Rain',
filename: 'rain.mp3',
storageUrl: 'sounds/rain.mp3',
},
];
function SoundList() {
const { playSound, isPlaying } = useSoundPlayback();
return (
<View>
{sounds.map(sound => (
<Button
key={sound.id}
onPress={() => playSound(sound)}
disabled={isPlaying(sound.id)}
>
{sound.name}
</Button>
))}
</View>
);
}Download Progress
function SoundPlayer() {
const { playSound, downloadProgress, downloadingSoundId } = useSoundPlayback();
const handlePlay = (sound: Sound) => {
playSound(
sound,
{ isLooping: true },
(progress) => {
console.log(`Download: ${Math.round(progress * 100)}%`);
}
);
};
return (
<View>
{downloadingSoundId && (
<ProgressBar value={downloadProgress} />
)}
</View>
);
}License
MIT
Author
Ümit UZ [email protected]
