Search code examples
react-nativeaudioexpo-av

Expo AV React Native Local Sound File issue


I am trying to create an audio player with react native and expo av. I can play online remote files (through uri) just fine, and my code works well. However, whenever I attempt to play a local file, it throws the error: [Unhandled promise rejection: Error: Cannot load an AV asset from a null playback source]. Most of my code for audio handling right now is dealt with through handleAudioPlayPause, which gets called on a button press. How can I get this program to play local files without an issue? Thanks

const audio = {
  filename: 'Audio file 1',
  uri:
  require('../assets/sounds/hello.mp3'), //this does not work
    // 'https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba.mp3', // this works
};

...

const [isPlaying, setIsPlaying] = useState(false);
const [playbackObject, setPlaybackObject] = useState<any | null>(null);
const [playbackStatus, setPlaybackStatus] = useState<any | null>(null);
useEffect(() => {
    if (playbackObject === null) {
      setPlaybackObject(new Audio.Sound());
    }
  }, []);
   const handleAudioPlayPause = async () => {
    if (playbackObject !== null && playbackStatus === null) {
      const status = await playbackObject.loadAsync(
        { uri: audio.uri },
        { shouldPlay: true }
      );
      setIsPlaying(true);
      return setPlaybackStatus(status);
    }

    // It will pause our audio
    if (playbackStatus.isPlaying) {
      const status = await playbackObject.pauseAsync();
      setIsPlaying(false);
      return setPlaybackStatus(status);
    }

    // It will resume our audio
    if (!playbackStatus.isPlaying) {
      const status = await playbackObject.playAsync();
      console.log(status);
      setIsPlaying(true);
      return setPlaybackStatus(status);
    }
  };
  

Solution

  • See there are different ways to load an audio file

    1. For remote Files use it as you were doing
    const status = await playbackObject.loadAsync(
      { uri: audio.uri }, // For remote files we have to place uri like this
      { shouldPlay: true }
    );
    
    1. But for local files, you have to use it like this,
    const status = await playbackObject.loadAsync(
      audio.uri, // For local files we have to use it like this
      { shouldPlay: true }
    );
    

    Working Example here