React Native Video Recording, Saving, and Playback

I’m working on a video app for React Native that records video, saves it, and plays it back. This post is to explain how I did it.

Choosing a Video Recording Module

I tried a few different options before I settled on one that worked for me. I tried react-native-camera, react-native-camera-kit, and react-native-beautiful-video-recorder. I ended up going with react-native-beautiful-video-recorder, it has a nice interface for recording video, and it was the easiest to get working.

The react-native-camera-kit module by Tesla was very promising, but it just didn’t work well for me. The capture button was missing on the camera screen component, and the flash button was invisible. I probably did something wrong, but I just didn’t have time to fiddle with it.

You can record and capture with the react-native-camera, but you need to build the UI yourself. It gives you a component for the screen, then you add your own buttons. I wanted something that already had some sort of UI.

Video Recorder Installation Tips

I followed the installation instructions for the react-native-beautiful-video-recorder, but got an error about custom icons on iOS. To fix this, I followed the instructions in this article to add a Fonts folder to my project and add the font files there.

After adding the Fonts group in my app folder, and adding the MaterialIcons.ttf file into it, I also added MaterialIcons.ttf under “Fonts provided by application” in my info.plist via Xcode.

Recorder Implementation

I mostly followed the docs to implement the recorder, the only thing that tripped me up a little bit was using functional components instead of a class. The docs are all in a class, so I implemented useRef() for the camera reference.

import VideoRecorder from 'react-native-beautiful-video-recorder';

const App = () => {
 const cameraRef = useRef(null);

 const videoRecord = async () => {
    if( cameraRef && cameraRef.current ) {{ maxLength: 30 },(data) => {
        console.log('captured data', data); // data.uri is the file path

 return (
  <VideoRecorder ref={cameraRef} />
  <Button onPress={ () => videoRecord() }>Open Recorder</Button>


This gives you a nice full screen video preview, a record button, and a check mark you can click when you are done.

The only thing I don’t like about this recorder is that the close icon is hidden behind the status bar. There is probably a simple fix for this, but I haven’t had time to dig into it.

Saving Videos

You have a few options for saving videos. You could offload them to a server, save to a local app folder, or save to the camera roll. I opted to save the videos in a local folder, and allow the user to save them to the camera roll as a backup since the videos will be deleted if the app is uninstalled.

To do this I used @react-native-community/cameraroll. After installing, the implementation is very simple. I just added data.uri ) in the callback function from the video recorder.

I also use Async Storage along with useState() to keep the video uris handy for playback. For more information, here is a great post on all the storage options you have in React Native.

Video Playback

For video playback, I chose the react-native-video module. It gives you a simple component that takes a uri and some options, and uses the native platform video player.

To implement this player, install following the instructions on their repo. (Don’t forget the npx pod install step any time you add a new module).

<Video source={{uri: yourURI }}   // Can be a URL or a local file.
          ref={playerRef}                                      // Store reference
          onBuffer={console.log('buffering')}                // Callback when remote video is buffering
          onError={ err => console.warn(err)}               // Callback when video cannot be loaded
          style={styles.backgroundVideo} />

Just like the recorder, you can use useRef() for the player reference. Controls and fullscreen default to false, so I added those. I also found it worked best with a set height and width.


Get more great content like this, enter your email below.


Loading comments...

Leave a comment

Your email address will not be published. Required fields are marked *