After a lot of testing with expo-av in a development build I can't find a way to play an audio efficiently.
Here are my 3 different ways, what's should be the better one and why? I'm having the "Player doesn't exist" error sometimes and after no more sounds are played... This this GitHub thread
In the first example the "audioRef" is defined as:
import { Audio } from 'expo-av';
const soundPath= require('sound.mp3');
const soundRef = useRef(new Audio.Sound());
soundRef.current.loadAsync(soundPath, {}); // {} = empty options
export const PlayAudio = async (audioRef, fromStart = true) => {
try {
const result = await audioRef.current.getStatusAsync();
if (result.isLoaded) {
if (result.isPlaying === false) {
if (fromStart) {
audioRef.current.playFromPositionAsync(0);
} else {
audioRef.current.playAsync();
}
} else if (fromStart) {
audioRef.current.pauseAsync();
audioRef.current.playFromPositionAsync(0);
}
}
} catch (e) {
console.error('Error playing Audio : ', e);
}
};
The two next examples take a "requiredPath" parameter which is just something like:
const requiredPath = require('sound.mp3')
export const PlayAudioBis = async (requiredPath, options = {}) => {
// LOAD
const sound = new Audio.Sound();
try {
await sound.loadAsync(requiredPath, options);
} catch (e) {
console.error('Error Loading Audio : ', e);
}
// PLAY
try {
const result = await sound.getStatusAsync();
if (result.isLoaded) {
await sound.playAsync();
}
} catch (e) {
console.error('Error playing Audio : ', e);
}
// UNLOAD
try {
await sound.unloadAsync();
} catch (e) {
console.error('Error unlaoding Audio : ', e);
}
};
export const PlayAudioTer = (requiredPath) => {
Audio.Sound.createAsync(requiredPath, { shouldPlay: true })
.then((res) => {
res.sound.setOnPlaybackStatusUpdate((status) => {
if (!status.didJustFinish) {
return;
}
res.sound.unloadAsync().catch((e) => {
console.error('Error unloading Audio : ', e);
});
});
})
.catch((e) => {
console.error('Error creating Audio : ', e);
});
};