react-native-queue-player
v1.0.8
Published
Nitro Modules audio playback library for React Native — gapless, EQ, crossfade, automotive, voice, casting
Downloads
971
Maintainers
Readme
react-native-queue-player
A complete audio playback library for React Native — gapless and crossfade engines, a 10-band equalizer, an FFT visualizer, ReplayGain loudness normalization, look-ahead disk caching, casting (Chromecast + AirPlay), automotive (CarPlay + Android Auto), and voice control (SiriKit + Google Assistant), all in one Nitro-powered package.
📖 Documentation: https://ghenry22.github.io/react-native-queue-player/
Features
- Gapless and crossfade playback — switch engines at runtime; configurable crossfade duration.
- Queue management — set / add / insert / move / remove, jump to index, skip next/previous, start-at-index ("play album from track N").
- Repeat and shuffle — off / queue / track repeat; one-shot shuffle.
- 10-band equalizer — ISO-frequency bands, built-in and custom presets.
- FFT visualizer — real-time frequency/waveform frames for custom visualizations.
- ReplayGain — track and album loudness normalization for tagged media.
- Look-ahead cache — proactive disk prefetch of upcoming streamed tracks, with a configurable size budget.
- Casting — Chromecast and AirPlay, including a native Android AirPlay sender.
- Automotive — CarPlay and Android Auto browse trees and playback.
- Voice — SiriKit (
INPlayMediaIntent) on iOS and Google Assistant on Android. - Background playback — lock-screen / Now Playing controls and remote commands handled natively.
- Remote-control skip mode — choose track skip or interval skip (jump ±N seconds) for the lock screen / notification, adjustable at runtime.
- Sleep timer — pause after a duration or at the end of the current track, with a volume fade; runs on a native wall-clock deadline.
- Now Playing format — codec, container, sample rate, bitrate, and ReplayGain metadata for the active track.
- React hooks —
useProgress,usePlaybackState,useActiveTrack,useCanSkip,useSleepTimer,useEqualizer,useVisualizerState,useLookaheadCache,useNowPlayingFormat,useCast,useAudioRoute.
Requirements
- React Native with the New Architecture enabled.
react-native-nitro-modules(peer dependency).- iOS 15+ (the Chromecast subspec requires iOS 15).
- Android
minSdk24+. - Expo config-plugin support (the native setup is driven by the bundled Expo plugin).
Installation
npm install react-native-queue-player react-native-nitro-modulesreact-native-nitro-modules is required because this library is built on Nitro Modules.
Add the Expo config plugin to your app config and enable the optional native integrations you need:
{
"expo": {
"plugins": [
["react-native-queue-player", { "carplay": false, "siri": true, "chromecast": true }]
]
}
}The plugin wires up the iOS Info.plist keys, entitlements, AppDelegate hooks, and the Chromecast pod automatically. On Android the library's manifest (services, permissions, media-session components) is merged in for you. See Setup & manual configuration for the steps you still need to do by hand.
Quick start
import { getTrackPlayer } from 'react-native-queue-player';
const player = getTrackPlayer();
// One-time setup at app start.
await player.configure({ audioContentType: 'music' });
// Load a queue and play. Only `url` is required on each track.
await player.setQueue([
{ url: 'https://stream.example/track1.mp3', title: 'One', artist: 'Artist', album: 'Album', duration: 180 },
{ url: 'https://stream.example/track2.mp3', title: 'Two', artist: 'Artist', album: 'Album', duration: 200 },
]);
await player.play();In React components, hooks subscribe to native event streams directly:
import {
useActiveTrack,
usePlaybackState,
useProgress,
useCanSkip,
} from 'react-native-queue-player';
function NowPlaying() {
const { track } = useActiveTrack();
const { state } = usePlaybackState();
const { position, duration } = useProgress();
const { canSkipNext, canSkipPrevious } = useCanSkip();
if (track == null) return <Text>No track loaded</Text>;
return (
<View>
<Text>{track.title} — {track.artist}</Text>
<Text>{state} · {position.toFixed(1)} / {duration.toFixed(1)}</Text>
{/* transport buttons read canSkipNext / canSkipPrevious */}
</View>
);
}The player is a singleton — getTrackPlayer() always returns the same instance. There is no class to instantiate. The same pattern applies to getEqualizer(), getVisualizer(), and getCastManager().
Manual configuration
Most native setup is automatic (Nitro autolinking + the Android manifest merge + the Expo plugin). A few things you must do by hand — see the Setup & manual configuration guide for full detail:
iOS background audio — add
audiotoUIBackgroundModesin your app config (ios.infoPlist). This is the one core background-playback step the plugin does not set for you:{ "expo": { "ios": { "infoPlist": { "UIBackgroundModes": ["audio"] } } } }Enable the integrations you need via the plugin flags (
carplay,siri,chromecast).Initialize the player early — call
configure()once at app start. If you use automotive or voice, the system can cold-start your app's JS without mounting any UI, so runconfigure()(andregisterPlaybackService()) from a bootstrap module imported before your app entry:// index.js import './src/playerBootstrap'; // runs configure() + registerPlaybackService() on every cold start import 'expo-router/entry';// src/playerBootstrap.ts import { getTrackPlayer, registerPlaybackService } from 'react-native-queue-player'; void (async () => { await getTrackPlayer().configure({ audioContentType: 'music' }); registerPlaybackService(() => ({ // automotive / voice browse + search handlers (see the automotive & voice guides) })); })();Android runtime permissions — request
POST_NOTIFICATIONS(and, on newer Android, local-network access for casting) at runtime from your app.
Lock-screen / Now Playing controls and remote commands work automatically once the player is configured — you do not register a service to handle them.
Common UX patterns
Apple-Music-style "tap Previous restarts when position > 3s"
The library ships the primitive (canSkipPrevious = "is there a previous track under the current repeat mode") and leaves the policy (rewind-vs-skip threshold) to your app:
import { getTrackPlayer, useProgress } from 'react-native-queue-player';
function PreviousButton() {
const { position } = useProgress();
const onPress = async () => {
const player = getTrackPlayer();
if (position > 3) await player.seekTo(0);
else await player.skipToPrevious();
};
return /* your <Button> here */;
}The 3-second threshold is the Apple Music default; tune to taste.
Skip-button enable/disable from useCanSkip
canSkipNext / canSkipPrevious already account for repeat mode: under off they go false at queue boundaries; under queue they wrap and stay true; under track they stay true.
const { canSkipNext, canSkipPrevious } = useCanSkip();
<Button onPress={onPrevious} disabled={!canSkipPrevious} />
<Button onPress={onNext} disabled={!canSkipNext} />If you adopt the >3s rewind pattern above, you may prefer to keep Previous enabled whenever there's an active track (so the user can rewind from track 1) — drive disabled from track == null instead.
Documentation
Full guides and API reference: https://ghenry22.github.io/react-native-queue-player/
- Quick start
- Setup & manual configuration
- CarPlay · Android Auto · Voice · Casting
- API reference
- Migrating from react-native-track-player v4.x
Contributing
License
Apache-2.0
