This commit is contained in:
2025-08-31 12:41:05 +08:00
parent fd9d498e3c
commit 67feea9443
6 changed files with 150 additions and 25 deletions

View File

@@ -14,7 +14,10 @@ const AudioState = {
playback: {
audioElement: null,
isPlaying: false,
audioChunks: [] // 存储接收到的音频块
audioChunks: [], // 存储接收到的音频块
audioQueue: [], // 音频队列,用于流式播放
isStreamPlaying: false, // 是否正在流式播放
currentAudioIndex: 0 // 当前播放的音频索引
},
websocket: {
connection: null,
@@ -178,12 +181,13 @@ const WebSocketManager = {
UIController.toggleElement('thinkingIndicator', false);
UIController.setStartRecordButtonEnabled(true);
// 合并所有音频块并播放
if (AudioState.playback.audioChunks.length > 0) {
console.log('开始合并和播放音频');
this.combineAndPlayAudio();
} else {
console.warn('没有收到音频数据,无法播放');
// 标记流式播放结束
AudioState.playback.isStreamPlaying = false;
// 如果有音频数据但尚未开始播放,则开始播放
if (AudioState.playback.audioQueue.length > 0 && !AudioState.playback.isPlaying) {
console.log('开始播放队列中的音频');
AudioPlayer.processAudioQueue();
}
break;
@@ -192,6 +196,9 @@ const WebSocketManager = {
console.error('收到错误消息:', data.message);
UIController.toggleElement('thinkingIndicator', false);
UIController.setStartRecordButtonEnabled(true);
// 重置流式播放状态
AudioState.playback.isStreamPlaying = false;
AudioState.playback.audioQueue = [];
alert('处理失败: ' + data.message);
break;
@@ -206,8 +213,20 @@ const WebSocketManager = {
// 二进制音频数据
console.log('收到音频数据,大小:', event.data.size);
console.log('音频数据类型:', event.data.type);
// 保存到原始音频块数组(保持原有逻辑)
AudioState.playback.audioChunks.push(event.data);
console.log('当前音频块数量:', AudioState.playback.audioChunks.length);
// 添加到音频队列(用于流式播放)
AudioState.playback.audioQueue.push(event.data);
console.log('当前音频队列长度:', AudioState.playback.audioQueue.length);
// 如果尚未开始流式播放,则开始播放
if (!AudioState.playback.isStreamPlaying && !AudioState.playback.isPlaying) {
console.log('开始流式播放音频');
AudioState.playback.isStreamPlaying = true;
AudioPlayer.processAudioQueue();
}
}
},
@@ -355,6 +374,64 @@ const AudioPlayer = {
const currentTime = AudioState.playback.audioElement.currentTime;
const duration = AudioState.playback.audioElement.duration;
UIController.updateTimeDisplay(currentTime, duration);
},
// 初始化流式播放器
initStreamPlayer() {
// 创建新的音频元素用于流式播放
if (!AudioState.playback.streamAudioElement) {
AudioState.playback.streamAudioElement = new Audio();
// 监听音频结束事件
AudioState.playback.streamAudioElement.addEventListener('ended', () => {
// 当前音频播放完毕,处理队列中的下一个音频
this.processAudioQueue();
});
// 监听错误事件
AudioState.playback.streamAudioElement.addEventListener('error', (e) => {
console.error('流式播放音频错误:', e);
// 即使出错,也继续处理队列中的下一个音频
this.processAudioQueue();
});
}
},
// 处理音频队列
processAudioQueue() {
// 如果正在播放或队列为空,则返回
if (AudioState.playback.isStreamPlaying || AudioState.playback.audioQueue.length === 0) {
AudioState.playback.isStreamPlaying = false;
return;
}
// 设置播放状态
AudioState.playback.isStreamPlaying = true;
// 从队列中取出第一个音频块
const audioBlob = AudioState.playback.audioQueue.shift();
// 创建音频URL
const audioUrl = URL.createObjectURL(audioBlob);
// 设置音频源并播放
AudioState.playback.streamAudioElement.src = audioUrl;
AudioState.playback.streamAudioElement.play()
.then(() => {
console.log('开始播放音频块');
})
.catch(error => {
console.error('播放音频块失败:', error);
// 播放失败,继续处理下一个
AudioState.playback.isStreamPlaying = false;
this.processAudioQueue();
})
.finally(() => {
// 播放完成后释放URL对象
setTimeout(() => {
URL.revokeObjectURL(audioUrl);
}, 1000);
});
}
};
@@ -589,10 +666,12 @@ const RecordingManager = {
};
// ==================== 初始化 ====================
// 页面加载完成后初始化
function initializeApp() {
console.log('开始初始化学伴录音功能...');
// 初始化流式播放器
AudioPlayer.initStreamPlayer();
// 检查DOM是否已就绪
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {