Blog
How To Integrate Offline Video Playback in Your Expo App

How To Integrate Offline Video Playback in Your Expo App

In this guide, we'll walk through how to integrate offline video playback in your Expo app using react-native-video and Offline Video SDK. Building on our previous post about setting up react-native-video, we'll now add support for downloading videos so users can watch content even when they're offline. You'll learn how to generate your API key on the SDK platform, install and configure stream-downloader, and connect it with react-native-video. At the end, we'll also share helpful resources, docs, and starter kit to get you going faster.
Tags
React Native
React Native Video
Tutorial
Expo
HLS

Why Offline Video Playback Matters

Offline playback is essential for video-heavy apps where users might not always have a stable internet connection - think travel, commuting, or regions with limited connectivity. By allowing your users to download videos directly to their device, you improve reliability, user experience, and engagement.

Step-by-Step Guide

Step 1: Prerequisites

Before we begin, make sure you’ve already set up react-native-video in your Expo project. If you haven’t yet, check out our earlier tutorial on how to integrate react-native-video with Expo.

Step 2: Generate Your API Key

To securely handle downloads, you’ll need an API key from the SDK platform:


1. Sign up to your SDK platform dashboard.


2. Verify Your Email and Navigate to Create Application.


3. Create an application and then attach the stream-downloader plugin - it will automatically generate an API key and a GitHub token for you.


4. Now that you have your API key ready, there’s also a quick tutorial on how to get started, but you can just continue here with this guide.

Step 3: Install Offline Video SDK Package

Before you install the package, you need to add your GitHub token to the .npmrc file (the one you got while creating the app - you can find it in the Package Configuration section - look image above).

@TheWidlarzGroup:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=ghp_your_token_here

Next you will be able to safely download the package:

npm install @TheWidlarzGroup/react-native-video-stream-downloader

Lastly remember to add the code snippet below to your android/app/build.gradle file:

dependencies {
	  implementation fileTree(dir: "../../node_modules/@TheWidlarzGroup/react-native-video-stream-downloader/native-libs", include: ["*.aar"])
	  //...
}

Step 4: Import Everything You Need and Register API

Now you will be able to import library into your VideoComponent.tsx for example:

import {
  deleteDownloadedAsset,
  downloadStream,
  getDownloadedAssets,
  getDownloadsStatus,
  registerPlugin,
  useEvent,
  type DownloadStatus,
  type DownloadedAsset,
} from '@TheWidlarzGroup/react-native-video-stream-downloader';

import React, { useEffect, useState } from 'react';
import { Alert, Image, Text, TouchableOpacity, View } from 'react-native';
import Video from 'react-native-video';

And than to make library work you need to register API key:

const API_KEY = 'YOUR_API_KEY_HERE';

useEffect(() => {
  const initializeSDK = async () => {
    try {
      await registerPlugin(API_KEY);
      await refreshData();
    } catch (error) {
      console.error('Error initializing SDK:', error);
    }
  };
  initializeSDK();
}, []);

Step 5: Listen to Downloads

The SDK emits two important events:
- onDownloadProgress -> progress update
- onDownloadEnd -> when download is finished

Hook into them to keep your state up to date:

useEvent('onDownloadProgress', async () => {
  await refreshData();
});

useEvent('onDownloadEnd', async () => {
  await refreshData();
});

Manage state with useState:

const [downloads, setDownloads] = useState<DownloadStatus[]>([]);
const [assets, setAssets] = useState<DownloadedAsset[]>([]);

const refreshData = async () => {
  const [downloadStatuses, downloadedAssets] = await Promise.all([
    getDownloadsStatus(),
    getDownloadedAssets(),
  ]);
  setDownloads(downloadStatuses);
  setAssets(downloadedAssets);
};

Step 6: Start Downloading and Deleting Video:

Create helper functions to start a download and remove a video:

const startDownload = async () => {
  try {
    await downloadStream(videoUrl);
    await refreshData();
  } catch (error) {
    Alert.alert('Download Error', 'Failed to start download.');
  }
};

const deleteDownload = async () => {
  const asset = assets.find((a) => a.url === videoUrl);
  if (asset) {
    await deleteDownloadedAsset(asset.id);
    await refreshData();
  }
};

Step 7: Play Offline Video

Once downloaded, you can play videos directly from the local file system:

const [currentVideoUri, setCurrentVideoUri] = useState<string | null>(null);

const playOffline = () => {
  const asset = assets.find((a) => a.url === videoUrl);
  if (asset?.pathToFile) {
    setCurrentVideoUri(asset.pathToFile);
  } else {
    Alert.alert('Not available', 'Please download the video first.');
  }
};

Step 8: Build a Simple UI

Now connect everything with a simple UI:

{isDownloaded ? (
  <>
    <TouchableOpacity onPress={playOffline}>
      <Text>▶ Play</Text>
    </TouchableOpacity>
    <TouchableOpacity onPress={deleteDownload}>
      <Text>🗑 Delete</Text>
    </TouchableOpacity>
  </>
) : (
  <TouchableOpacity onPress={startDownload} disabled={downloadInProgress}>
    <Text>
      {downloadInProgress && downloadStatus
        ? `Downloading ${Math.round((downloadStatus.progress || 0) * 100)}%`
        : '⬇ Download'}
    </Text>
  </TouchableOpacity>
)}

Example App

We've also prepared a full Expo example app that demonstrates how to integrate the Offline Video SDK for offline playback. You can explore the source code, see the setup in action, and use it as a starting point for your own project.

👉 Check out the GitHub repository here: Example App on GitHub

You can further customize the implementation as you wish. Here are some helpful resources that might help you do that:

Helpful Resources

📚 react-native-video Documentation
📦 Offline Video SDK Documentation
🚀 Starter Kit to help you get up and running quickly
💬 Contact Us if you need help or want to discuss your use case

Summary:

1. Install and import the SDK + react-native-video.
2. Register Your API Key.
3. Listen to events (onDownloadProgress, onDownloadEnd).
4. Implement download/delete logic.
5. Play videos from local storage when offline.
6. Create a UI with Download, Play, and Delete buttons + progress updates.

This gives you a fully working offline video system in React Native and Expo 🎬✨

Wrapping Up

That’s it! You’ve now integrated offline video playback into your Expo app. With this setup, your users can download videos for later viewing, boosting engagement and reliability!

React Native
React Native Video
Tutorial
Expo
HLS

How to Play Video in an Expo App (Using react-native-video)

React Native Video
React Native
Tutorial
Expo
Want to add video playback to your Expo project? In this guide, we'll walk you through integrating react-native-video with Expo so you can play, pause, and customize videos in your React Native app. We'll cover installation, setup, and common pitfalls when using react-native-video in managed or bare workflow projects. By the end, you'll know how to seamlessly embed video players with fullscreen support, controls, and performance optimizations inside your Expo app.
See article
Do you need help with developing react solutions?

Leave your contact info and we’ll be in touch with you shortly

Leave contact info
Become one of our 10+ ambassadors and earn real $$$.