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:
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:
// 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 useSoundEffectIt's supposed to be used like this:
// 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 <3That's about it for now, I'll see you soon
With love from wituz
1
1