Expo-AV not playing audio after a while, and how to fix it

08/28/2024 08:36, 2 years ago

Recently, I was working on my game AI Against Humanity, where I encountered a bug in Expo-AV.
Namely, I was trying to play sounds.
And while it at first worked fine, after playing sounds for a few minutes, eventually I would run into this issue:

1
2
3

Unhandled Promise Rejection
"Player doesn't exist" or sometimes "Player not found"

This was due to a memory leak in my application.
When you load sounds with await Audio.Sound.createAsync(source), it doesn't automatically unload it.

So I just wrote a custom hook, useSoundEffect, that you can use out of the box in your Expo app as well.
Here it is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// useSoundEffect.ts
import { Audio } from "expo-av"
import { useEffect, useState } from "react"

function useSoundEffect(source: any) {
  const [sound, setSound] = useState<Audio.Sound>(null)

  useEffect(() => {
    let _sound: Audio.SoundObject = null
    const loadSound = async () => {
      _sound = await Audio.Sound.createAsync(source)
      setSound(_sound.sound)
    }
    loadSound()

    return () => {
      _sound?.sound?.unloadAsync()
    } 
  }, [])

  return sound
}

export default useSoundEffect

It's supposed to be used like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// First I add a Typescript definition to import .mp3 files
// If you want to be fancy, you can always specify a type for any
// I just went the quick way to get it working
declare module "*.mp3" {
  const value: any;
  export default value;
}

// Then somewhere in the code, I can import the sound
import SoundFanfare from '@page/against-humanity/sounds/fanfare.mp3'

// And then, in any component, you can just use the hook like so
const soundFanfare = useSoundEffect(SoundFanfare)

// Then at any time, you can play the sound
const playSound = () => {
  soundFanfare.playAsync()
}

// And you don't even have to worry about the unloading <3

That's about it for now, I'll see you soon
With love from wituz

1

1