expo-av, expo-media-library, react-native-sound, and react-native-video are essential tools for handling media in React Native applications, but they serve distinct architectural roles. expo-av and react-native-sound focus on audio playback, while expo-av and react-native-video handle video rendering. expo-media-library stands apart by managing access to the device's photo and media storage rather than playback. Choosing the right combination depends on whether you are using the Expo managed workflow, require advanced video features like DRM, or need to save and retrieve files from the user's gallery.
Building media features in React Native requires choosing between Expo's unified modules and community-driven native packages. expo-av, expo-media-library, react-native-sound, and react-native-video each solve specific parts of the media puzzle. Let's compare how they handle playback, storage access, and configuration.
expo-av provides a modern, promise-based API for loading and playing sound files. It works seamlessly in both managed and bare workflows.
// expo-av: Modern async/await API
import { Audio } from 'expo-av';
async function playSound() {
const { sound } = await Audio.Sound.createAsync(
require('./assets/sound.mp3')
);
await sound.playAsync();
}
react-native-sound uses a callback-based constructor pattern. It is older and requires manual management of the sound instance.
// react-native-sound: Callback-based API
import Sound from 'react-native-sound';
const whoosh = new Sound('whoosh.mp3', Sound.MAIN_BUNDLE, (error) => {
if (!error) whoosh.play();
});
react-native-video is designed for video, not audio-only. Using it for audio is possible but inefficient as it initializes a video renderer.
// react-native-video: Not intended for audio-only
// Requires a Video component even for audio streams
import Video from 'react-native-video';
// <Video source={{uri: 'audio.mp3'}} />
// Avoid this for pure audio; use expo-av instead.
expo-media-library does not handle playback. It manages storage access. Trying to play media directly with this package will fail.
// expo-media-library: No playback capability
// This package saves or retrieves assets, does not play them
import * as MediaLibrary from 'expo-media-library';
// Use with expo-av to play retrieved assets
// const asset = await MediaLibrary.getAssetAsync(id);
expo-av includes a <Video> component that covers most standard needs like streaming, local files, and basic controls.
// expo-av: Unified Video component
import { Video } from 'expo-av';
export default function Player() {
return <Video source={{ uri: 'video.mp4' }} useNativeControls />;
}
react-native-video offers deeper customization for video, including DRM, custom control layers, and background playback configuration.
// react-native-video: Advanced Video component
import Video from 'react-native-video';
export default function Player() {
return <Video source={{ uri: 'video.mp4' }} controls={true} />;
}
react-native-sound does not support video playback. It is strictly for audio assets.
// react-native-sound: No video support
// Cannot render video streams
import Sound from 'react-native-sound';
// No Video component available
expo-media-library does not play video. It retrieves video assets from the gallery, which you must then pass to a player like expo-av.
// expo-media-library: Retrieves video assets only
import * as MediaLibrary from 'expo-media-library';
// Get video URI, then pass to expo-av Video component
const assets = await MediaLibrary.getAssetsAsync({ mediaType: 'video' });
expo-media-library is the standard for saving and loading media from the device gallery in Expo projects.
// expo-media-library: Save and load assets
import * as MediaLibrary from 'expo-media-library';
await MediaLibrary.requestPermissionsAsync();
const assets = await MediaLibrary.getAssetsAsync({ first: 10 });
expo-av does not access the gallery directly. It plays media from URIs provided by other modules.
// expo-av: No gallery access
// Requires URI from another source
import { Video } from 'expo-av';
// <Video source={{ uri: '...' }} />
// Must get URI via expo-media-library or network
react-native-video does not access the gallery. It relies on external modules to provide file paths or URIs.
// react-native-video: No gallery access
import Video from 'react-native-video';
// Source must be provided manually
// <Video source={{ uri: filePath }} />
react-native-sound does not access the gallery. It plays bundled assets or network URLs.
// react-native-sound: No gallery access
import Sound from 'react-native-sound';
// Plays from app bundle or network
// new Sound('file.mp3', Sound.MAIN_BUNDLE)
expo-av handles permissions automatically in Managed Workflow. In Bare Workflow, it requires config plugins.
// expo-av: Managed Workflow handles permissions
// app.json configuration
{
"expo": {
"plugins": ["expo-av"]
}
}
expo-media-library requires explicit permission requests in code and configuration in app.json for iOS and Android.
// expo-media-library: Explicit permission request
import * as MediaLibrary from 'expo-media-library';
const { status } = await MediaLibrary.requestPermissionsAsync();
// Check status === 'granted'
react-native-video requires manual linking or config plugins in Expo. You must manage native dependencies yourself in bare workflows.
// react-native-video: Manual native config
// Requires pod install for iOS
// Requires gradle changes for Android
// npx pod-install (iOS)
react-native-sound requires manual linking in older React Native versions or config plugins in Expo. It is less integrated than Expo modules.
// react-native-sound: Manual linking
// Often requires react-native-link or manual native setup
// Less seamless than expo-av in Expo projects
While these packages serve different roles, they share common patterns in the React Native ecosystem.
expo-av and react-native-video both provide React components for rendering media.// Both use React components for video
// expo-av
import { Video } from 'expo-av';
<Video source={{ uri }} />
// react-native-video
import Video from 'react-native-video';
<Video source={{ uri }} />
expo-av and react-native-sound both manage audio lifecycle.// Both require cleanup
// expo-av
await sound.unloadAsync();
// react-native-sound
whoosh.release();
// All require permissions
// iOS: Info.plist entries
// Android: AndroidManifest.xml entries
| Feature | expo-av | expo-media-library | react-native-sound | react-native-video |
|---|---|---|---|---|
| Audio Playback | โ Yes | โ No | โ Yes | โ ๏ธ Possible |
| Video Playback | โ Yes | โ No | โ No | โ Yes |
| Gallery Access | โ No | โ Yes | โ No | โ No |
| Expo Managed | โ Native | โ Native | โ ๏ธ Config Plugin | โ ๏ธ Config Plugin |
| Advanced Video | โ ๏ธ Basic | โ No | โ No | โ Advanced |
expo-av is the all-rounder ๐งฐ โ best for teams using Expo who need reliable audio and video without native hassle. It covers 90% of use cases.
expo-media-library is the storage manager ๐๏ธ โ essential if your app saves photos or videos to the device. It pairs with expo-av for playback.
react-native-video is the specialist ๐ฌ โ choose this for complex video needs like DRM or custom controls in bare workflows.
react-native-sound is the legacy tool ๐ฐ๏ธ โ only use for specific bare workflow needs where expo-av isn't an option. Prefer expo-av for new projects.
Final Thought: For most modern React Native apps, start with expo-av and expo-media-library. Only reach for react-native-video if you hit the limits of Expo's video component.
Choose expo-av if you are building with Expo Managed Workflow and need a unified solution for both audio and video playback. It offers a consistent API, handles permissions gracefully within the Expo ecosystem, and receives regular updates alongside the SDK. It is the default choice for most standard media playback needs.
Choose expo-media-library if your app needs to save images or videos to the device gallery or read existing media from the user's storage. It does not play media; it manages access. Pair this with expo-av if you need to play the media you retrieve.
Choose react-native-sound only for legacy bare React Native projects requiring simple sound effects where expo-av cannot be integrated. It is largely considered legacy compared to modern alternatives, so evaluate expo-av or react-native-track-player first for new development.
Choose react-native-video if you need advanced video capabilities such as DRM support, custom control overlays, or picture-in-picture mode in a bare React Native workflow. It offers more granular control than expo-av but requires more complex native configuration.