添加声音连续播放

This commit is contained in:
kron
2025-11-12 11:39:17 +08:00
parent 59a2b173a6
commit 6b96087b68
3 changed files with 89 additions and 19 deletions

View File

@@ -88,6 +88,11 @@ class AudioManager {
this.isLoading = false;
this.loadingPromise = null;
// 连续播放队列相关属性
this.sequenceQueue = [];
this.sequenceIndex = 0;
this.isSequenceRunning = false;
// 网络状态相关
this.networkOnline = true;
this.pendingPlayKey = null;
@@ -206,6 +211,8 @@ class AudioManager {
this.currentPlayingKey = null;
}
this.allowPlayMap.set(key, false);
// 触发连续播放队列的衔接
this.onAudioEnded(key);
});
// 监听播放停止事件
@@ -263,16 +270,51 @@ class AudioManager {
this.createAudio(key);
}
// 播放指定音频
play(key) {
// 离线:缓存播放意图,待网络恢复后自动播放
// 播放指定音频或音频数组(数组则按顺序连续播放)
play(input) {
// 离线:缓存播放意图(可为字符串或数组),待网络恢复后自动播放
if (!this.networkOnline) {
this.pendingPlayKey = input;
debugLog(`网络不可用,记录播放意图: ${Array.isArray(input) ? input.join(',') : input}`);
return;
}
// 再次调用 play打断前面所有声音与队列
this.stopAll();
this.isSequenceRunning = false;
this.sequenceQueue = [];
this.sequenceIndex = 0;
if (Array.isArray(input)) {
// 过滤可播放的 key
const queue = input.filter((k) => !!audioFils[k]);
if (queue.length === 0) {
debugLog("连续播放队列为空或无效");
return;
}
this.sequenceQueue = queue;
this.sequenceIndex = 0;
this.isSequenceRunning = true;
// 开始播放队列的第一个
this._playSingle(queue[0], false);
} else if (typeof input === "string") {
this._playSingle(input, false);
} else {
debugLog("play 参数类型无效,仅支持字符串或字符串数组");
}
}
// 内部方法:播放单个 key
_playSingle(key, forceStopAll = false) {
if (!this.networkOnline) {
this.pendingPlayKey = key;
debugLog(`网络不可用,记录播放意图: ${key}`);
return;
}
// 覆盖播放:若当前播放且不是同一音频,先停止当前播放
if (this.currentPlayingKey && this.currentPlayingKey !== key) {
if (forceStopAll) {
this.stopAll();
} else if (this.currentPlayingKey && this.currentPlayingKey !== key) {
this.stop(this.currentPlayingKey);
}
@@ -303,6 +345,25 @@ class AudioManager {
}
}
// 连续播放:在某个音频结束后,若处于队列播放状态则继续下一个
onAudioEnded(key) {
if (!this.isSequenceRunning) return;
const currentKey = this.sequenceQueue[this.sequenceIndex];
if (currentKey !== key) return;
const nextIndex = this.sequenceIndex + 1;
if (nextIndex < this.sequenceQueue.length) {
this.sequenceIndex = nextIndex;
const nextKey = this.sequenceQueue[nextIndex];
this._playSingle(nextKey, false);
} else {
// 队列播放完成
this.isSequenceRunning = false;
this.sequenceQueue = [];
this.sequenceIndex = 0;
}
}
// 停止指定音频
stop(key) {
const audio = this.audioMap.get(key);

View File

@@ -22,26 +22,23 @@ const totalShot = ref(0);
watch(
() => tips.value,
(newVal) => {
let key = "";
if (newVal.includes("重回")) return;
if (newVal.includes("红队")) key = "请红方射箭";
if (newVal.includes("蓝队")) key = "请蓝方射箭";
if (!sound.value) return;
let key = [];
if (newVal.includes("重回")) return;
if (currentRoundEnded.value) {
currentRound.value += 1;
// 播放当前轮次语音
audioManager.play(
`${["一", "二", "三", "四", "五"][currentRound.value - 1]}`
);
key.push(`${["一", "二", "三", "四", "五"][currentRound.value - 1]}`);
}
// 延迟播放队伍提示音
setTimeout(
() => {
if (key) audioManager.play(newVal.includes("") ? "轮到你了" : key);
currentRoundEnded.value = false;
},
currentRoundEnded.value ? 1000 : 0
key.push(
newVal.includes("你")
? "轮到你了"
: newVal.includes("红队")
? "请红方射箭"
: "请蓝方射箭"
);
audioManager.play(key);
currentRoundEnded.value = false;
}
);

View File

@@ -26,6 +26,18 @@ onBeforeUnmount(() => {
<template>
<Container title="音频测试">
<view class="container">
<view>
<text>连续播放1</text>
<button hover-class="none" @click="playAudio(['第一轮', '请蓝方射箭'])">
播放
</button>
</view>
<view>
<text>连续播放2</text>
<button hover-class="none" @click="playAudio(['第二轮', '请红方射箭'])">
播放
</button>
</view>
<view v-for="key in Object.keys(audioFils)" :key="key">
<text>{{ key }}</text>
<text v-if="!loaded[key]">未加载</text>