|
@@ -22,6 +22,8 @@ export class StreamingAudioPlayer {
|
|
|
private startTime = 0 // 开始播放的时间戳
|
|
private startTime = 0 // 开始播放的时间戳
|
|
|
private lastDecodedDuration = 0 // 上次解码的总时长(用于计算增量)
|
|
private lastDecodedDuration = 0 // 上次解码的总时长(用于计算增量)
|
|
|
private decodedChunksCount = 0 // 已解码的块数
|
|
private decodedChunksCount = 0 // 已解码的块数
|
|
|
|
|
+ private hasEnded = false // 防止多次触发 onEnded
|
|
|
|
|
+ private activeSources = 0 // 正在播放的音频源数量
|
|
|
|
|
|
|
|
constructor(config: AudioPlayerConfig = {}) {
|
|
constructor(config: AudioPlayerConfig = {}) {
|
|
|
this.config = config
|
|
this.config = config
|
|
@@ -195,11 +197,15 @@ export class StreamingAudioPlayer {
|
|
|
// 计算播放时间(紧接着上一段)
|
|
// 计算播放时间(紧接着上一段)
|
|
|
const playTime = Math.max(this.lastPlayTime, this.audioContext.currentTime)
|
|
const playTime = Math.max(this.lastPlayTime, this.audioContext.currentTime)
|
|
|
|
|
|
|
|
- console.log(`🎵 播放增量音频: ${newDuration.toFixed(2)}秒 (跳过前${offsetTime.toFixed(2)}秒), 延迟: ${((playTime - this.audioContext.currentTime) * 1000).toFixed(0)}ms`)
|
|
|
|
|
|
|
+ // 增加活跃音频源计数
|
|
|
|
|
+ this.activeSources++
|
|
|
|
|
+ console.log(`🎵 播放增量音频: ${newDuration.toFixed(2)}秒 (跳过前${offsetTime.toFixed(2)}秒), 延迟: ${((playTime - this.audioContext.currentTime) * 1000).toFixed(0)}ms, 活跃源: ${this.activeSources}`)
|
|
|
|
|
|
|
|
// 设置结束回调
|
|
// 设置结束回调
|
|
|
source.onended = () => {
|
|
source.onended = () => {
|
|
|
- console.log('🎵 音频段播放完成')
|
|
|
|
|
|
|
+ // 减少活跃音频源计数
|
|
|
|
|
+ this.activeSources--
|
|
|
|
|
+ console.log(`🎵 音频段播放完成 (剩余活跃源: ${this.activeSources})`)
|
|
|
|
|
|
|
|
// 检查是否还有未解码的数据
|
|
// 检查是否还有未解码的数据
|
|
|
const hasNewChunks = this.audioChunks.length > this.decodedChunksCount
|
|
const hasNewChunks = this.audioChunks.length > this.decodedChunksCount
|
|
@@ -207,10 +213,16 @@ export class StreamingAudioPlayer {
|
|
|
if (hasNewChunks) {
|
|
if (hasNewChunks) {
|
|
|
console.log(`🔄 继续解码新的 ${this.audioChunks.length - this.decodedChunksCount} 个块`)
|
|
console.log(`🔄 继续解码新的 ${this.audioChunks.length - this.decodedChunksCount} 个块`)
|
|
|
this.decodeAndQueue()
|
|
this.decodeAndQueue()
|
|
|
- } else if (this.allChunksReceived) {
|
|
|
|
|
- console.log('✅ 所有音频播放完成')
|
|
|
|
|
|
|
+ } else if (this.allChunksReceived && this.activeSources === 0 && !this.hasEnded) {
|
|
|
|
|
+ // ⭐ 关键:所有块已接收 + 所有音频源都播放完成 + 未触发过结束
|
|
|
|
|
+ console.log('✅ 所有音频播放完成 - 触发 onEnded 回调')
|
|
|
this.playing = false
|
|
this.playing = false
|
|
|
|
|
+ this.hasEnded = true // 标记已结束,防止重复触发
|
|
|
this.config.onEnded?.()
|
|
this.config.onEnded?.()
|
|
|
|
|
+ } else if (this.hasEnded) {
|
|
|
|
|
+ console.log('⏭️ 已触发过 onEnded,跳过重复调用')
|
|
|
|
|
+ } else if (this.activeSources > 0) {
|
|
|
|
|
+ console.log(`⏳ 还有 ${this.activeSources} 个音频源在播放...`)
|
|
|
} else {
|
|
} else {
|
|
|
console.log('⏳ 等待更多音频块...')
|
|
console.log('⏳ 等待更多音频块...')
|
|
|
}
|
|
}
|
|
@@ -265,6 +277,7 @@ export class StreamingAudioPlayer {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
this.playing = false
|
|
this.playing = false
|
|
|
|
|
+ // 注意:不重置 activeSources,让 onended 自然触发递减
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
clear() {
|
|
clear() {
|
|
@@ -279,6 +292,8 @@ export class StreamingAudioPlayer {
|
|
|
this.startTime = 0
|
|
this.startTime = 0
|
|
|
this.lastDecodedDuration = 0
|
|
this.lastDecodedDuration = 0
|
|
|
this.decodedChunksCount = 0
|
|
this.decodedChunksCount = 0
|
|
|
|
|
+ this.hasEnded = false // 重置结束标志
|
|
|
|
|
+ this.activeSources = 0 // 重置活跃音频源计数
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
destroy() {
|
|
destroy() {
|