React Native: How to Load and Play Audio
By: Ross Bulat
Tags: JavaScript, App Development, React Native, Software Engineering, Programming

React Native: How to Load and Play Audio

Expo AV: Reliable Native Audio Support

This article introduces the expo-av package, a universal audio (playing and recording) and video module for React Native projects. The package is maintained by Expo, the go-to library for bootstrapping React Native projects targeting a range of platforms.

Audio packages have come and gone in the React Native ecosystem, most of which either do not work or have not been updated for a significant amount of time. When looking at packages to adopt — especially for critical tasks like audio playback — a reliable and well maintained package is needed. Major iOS updates are launched on a yearly basis and Android updates considerably more regularly. These updates sometimes come with breaking changes, so choosing reliable source code on the React Native side will be in every developers interest.

Note that react-native-audio has not been updated in over 2 years, and react-native-sound has been stagnant for over 1 year (since the time of writing this article); these packages should be avoided as they will not support the latest native APIs, and will lead to dead-end troubleshooting when they do not work in your project.

With all this being said, expo-av ticks all the boxes in terms of maintenance and platform support. With weekly downloads at >25,000, and the last update published a month ago (at the time of writing), it is a fairly strongly adopted package that the developer should have confidence using. Not all apps require audio, so it can be hard to gauge the popularity relative to the whole React Native ecosystem.

expo-av also has strong documentation that is kept up to date. The reader can visit the package on GitHub as the true source, but the majority of documentation is hosted on the Expo website, where there is a dedicated audio page along with an API reference page for the Expo AV module. It is this documentation that we’ll be referencing throughout this article as we build some audio tools.

What this article will cover

Now that I have hopefully persuaded you that Expo AV is the way to go with React Native audio, it is time to delve into some development. Instead of writing a standard tutorial of loading and playing an audio clip, we will make things more interesting to more closely reflect real-world use cases. After installation, this piece will:

Explain the audio loading and playing workflow and the key APIs needed to get audio working.

Walk through an audio controller class that loads, plays, resets and stops audio clips. This class will be separate from React components as to separate the audio logic from component logic.

Demonstrate how to load and manage multiple audio clips simultaneously. For this piece we will assume that a male and female audio clip need to be loaded, whereby the end-user can choose which gender to listen to. Of course, switching the gender can be achieved simply by toggling that gender via state management, but the corresponding audio itself must be loaded and available, ready to be played.

and audio clip need to be loaded, whereby the end-user can choose which gender to listen to. Of course, switching the gender can be achieved simply by toggling that gender via state management, but the corresponding audio itself must be loaded and available, ready to be played. Walk through a <PlayButton /> component, that will initialise the audio (request to load the audio files from a remote server), and manage the audio state. More specifically, we will visit concepts such as auto play, tap to play, tap to stop, and reflect this in component state. Another thing we need to manage with audio is the component state while the audio is being retrieved. This means asynchronously requesting the audio and waiting for it to be fully loaded before it can be played. This adds further (but needed) complexity into the component as to not attempt to play an unloaded audio file that would result in a runtime error.