Expoexpo-videoexpo-audioMediaReact Native

Playing Video and Audio in Expo (expo-video & expo-audio Guide)

expo-av is retired — here's how to play video and audio in Expo with the modern expo-video and expo-audio APIs. Learn useVideoPlayer, VideoView, useAudioPlayer, controls, and looping. SDK 54+ examples.

DeveloperMill2 min read

If you searched for "expo-av" you'll hit a wall: the Audio and Video APIs in expo-av are deprecated and removed in SDK 55. The modern replacements are expo-video and expo-audio — smaller, hook-based, and much easier to use. This guide shows how to play video and audio the right way today.

Install

npx expo install expo-video expo-audio

Play a video

Create a player with useVideoPlayer and render it with VideoView:

import { useVideoPlayer, VideoView } from "expo-video"
import { View } from "react-native"

const source =
  "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"

export default function Player() {
  const player = useVideoPlayer(source, (player) => {
    player.loop = true
    player.play()
  })

  return (
    <View style={{ flex: 1 }}>
      <VideoView
        style={{ width: "100%", height: 240 }}
        player={player}
        allowsFullscreen
        allowsPictureInPicture
      />
    </View>
  )
}

The second argument to useVideoPlayer is a setup callback — a great place to set loop, muted, or call play().

Control playback

The player object is imperative — call methods directly:

player.play()
player.pause()
player.replace(newSource) // switch to a different video
player.currentTime = 0    // seek to the start
player.muted = true

React to player state

Use the useEvent hook from expo to re-render when playback status changes:

import { useEvent } from "expo"

const { isPlaying } = useEvent(player, "playingChange", {
  isPlaying: player.playing,
})

// <Button title={isPlaying ? "Pause" : "Play"} onPress={() => (isPlaying ? player.pause() : player.play())} />

Play audio

expo-audio mirrors the same pattern with useAudioPlayer:

import { useAudioPlayer } from "expo-audio"
import { Button } from "react-native"

export default function Ping() {
  const player = useAudioPlayer(require("./assets/ping.mp3"))

  return <Button title="Play sound" onPress={() => player.play()} />
}

You can also stream remote audio by passing a URL string instead of a require.

Record audio

expo-audio also handles recording via useAudioRecorder — request microphone permission, record(), then stop() to get a file URI you can upload or play back.

Gotchas

  • Migrating from expo-av? Replace Video/Audio.Sound with useVideoPlayer/useAudioPlayer. There's no <Video> with a source prop anymore — the player is separate from the view.
  • Add the expo-video/expo-audio config plugins in app.json for background playback and mic permissions.
  • Set the audio session mode if you need sound to play in silent mode or continue in the background.

Next steps

Capturing media instead of playing it? See the expo-camera tutorial and expo-image-picker guide. See all ten in the top Expo SDK modules roundup.

Frequently asked questions

Is expo-av still supported?

No. The Audio and Video APIs in expo-av are deprecated and were removed in SDK 55. Use expo-video for video playback and expo-audio for audio. Both offer simpler, hook-based APIs than the old expo-av.

How do I play a video in Expo?

Install expo-video, create a player with the `useVideoPlayer(source)` hook, and render it with the `<VideoView player={player} />` component. You can auto-play and loop by configuring the player in the hook's setup callback.

How do I play a sound effect in Expo?

Install expo-audio, create a player with `useAudioPlayer(require('./sound.mp3'))`, then call `player.play()`. The hook manages the player's lifecycle for you.

Build it faster with a template

Production-ready Expo React Native templates with the patterns from this post already wired up.

Browse templates