如何使用Expo-AV实现多段音频按顺序依次播放?
Expo-AV 多段音频顺序播放实现方案
直接遍历调用播放方法会导致所有音频同时初始化并播放,核心解决思路是等待上一段音频播放完成后,再加载并播放下一段,以下两种方案均可实现:
方案一:基于 Async/Await 顺序执行
利用playAsync()返回的Promise结合async/await,逐个处理音频文件,确保上一段播放完成后再启动下一段:
import { Audio } from 'expo-av'; const sounds = ["../songs/song1.mp3", "../songs/song2.mp3", "../songs/song3.mp3"]; // 封装单个音频播放逻辑,返回播放完成的Promise async function playSingleSound(soundUri) { const soundObject = new Audio.Sound(); try { // 加载音频(本地资源用require,远程URL直接传字符串) await soundObject.loadAsync(require(soundUri)); // 开始播放 await soundObject.playAsync(); // 等待播放结束 await new Promise(resolve => { soundObject.setOnPlaybackStatusUpdate(status => { if (status.didJustFinish) { soundObject.unloadAsync(); // 释放音频资源 resolve(); } }); }); } catch (error) { console.error('音频播放失败:', error); await soundObject.unloadAsync(); } } // 顺序播放所有音频 async function playSoundsInOrder() { for (const uri of sounds) { await playSingleSound(uri); } } // 触发播放 playSoundsInOrder();
方案二:基于队列与播放事件监听
维护一个播放队列,监听当前音频的播放结束事件,自动启动下一段音频,适合需要动态添加音频的场景:
import { Audio } from 'expo-av'; let soundsQueue = ["../songs/song1.mp3", "../songs/song2.mp3", "../songs/song3.mp3"]; let currentSoundInstance = null; function playNext() { if (soundsQueue.length === 0) { console.log('全部音频播放完成'); return; } const nextUri = soundsQueue.shift(); currentSoundInstance = new Audio.Sound(); // 加载并播放下一段音频 currentSoundInstance.loadAsync(require(nextUri)) .then(() => currentSoundInstance.playAsync()) .catch(err => console.error('音频加载/播放出错:', err)); // 监听播放状态,结束后启动下一段 currentSoundInstance.setOnPlaybackStatusUpdate(status => { if (status.didJustFinish) { currentSoundInstance.unloadAsync().then(() => { currentSoundInstance = null; playNext(); }); } }); } // 启动队列播放 playNext();
注意事项
- 路径适配:本地资源需确保
require()的路径与项目结构匹配,远程音频URL可直接传入字符串,无需require。 - 资源释放:每段音频播放结束后调用
unloadAsync(),避免内存泄漏。 - 错误处理:添加异常捕获逻辑,防止单个音频播放失败导致整个流程中断。
内容的提问来源于stack exchange,提问作者ashketchup
相关产品推荐
相关产品推荐

