From b600114ed9aa0f59ed837d7ce9776353e557a5d9 Mon Sep 17 00:00:00 2001 From: Song367 <601337784@qq.com> Date: Mon, 28 Jul 2025 13:47:03 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A8=B3=E5=AE=9A=E5=88=87=E6=8D=A2=E8=A7=86?= =?UTF-8?q?=E9=A2=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chat_history.json | 273 +---------------------------------------- src/chat_with_audio.js | 2 +- src/index.js | 54 +++++++- src/message_history.js | 6 +- src/minimaxi_stream.js | 11 +- src/styles.css | 17 ++- 6 files changed, 74 insertions(+), 289 deletions(-) diff --git a/chat_history.json b/chat_history.json index 023ae74..0637a08 100644 --- a/chat_history.json +++ b/chat_history.json @@ -1,272 +1 @@ -[ - { - "role": "user", - "content": "你好。", - "timestamp": "2025-07-27T14:31:39.908Z" - }, - { - "role": "assistant", - "content": "哟,还这么客气呢?周末打算干啥呀? ", - "timestamp": "2025-07-27T14:31:39.908Z" - }, - { - "role": "user", - "content": "不打算干啥。", - "timestamp": "2025-07-27T14:31:52.513Z" - }, - { - "role": "assistant", - "content": "得嘞,那咱宅家咋样,我发现个超搞笑综艺。 ", - "timestamp": "2025-07-27T14:31:52.513Z" - }, - { - "role": "user", - "content": "哎,我不知道。", - "timestamp": "2025-07-27T14:32:00.781Z" - }, - { - "role": "assistant", - "content": "不知道啥呀?综艺还是宅家咋安排?要不咱叫点烧烤边吃边看? ", - "timestamp": "2025-07-27T14:32:00.781Z" - }, - { - "role": "user", - "content": "到咯,佢到咯,我做饭啊。", - "timestamp": "2025-07-27T14:32:06.301Z" - }, - { - "role": "assistant", - "content": "哟,背着我悄悄准备做饭啦!做啥好吃的,有我份不? ", - "timestamp": "2025-07-27T14:32:06.301Z" - }, - { - "role": "user", - "content": "到咯,佢到咯,我做饭啊。要3秒,要开大。", - "timestamp": "2025-07-27T14:32:08.465Z" - }, - { - "role": "assistant", - "content": "啥跟啥啊?说的我一头雾水。你是准备做饭吗?需不需要我帮你弄点啥,冰箱里还有鸡蛋和青菜呢。 ", - "timestamp": "2025-07-27T14:32:08.465Z" - }, - { - "role": "user", - "content": "Hello, hello.", - "timestamp": "2025-07-27T14:39:43.062Z" - }, - { - "role": "assistant", - "content": "别搁那hello了,快跟我说说你做饭啥情况,要开啥大?是火开大点吗? ", - "timestamp": "2025-07-27T14:39:43.062Z" - }, - { - "role": "user", - "content": "你说话啊。", - "timestamp": "2025-07-27T14:40:45.074Z" - }, - { - "role": "assistant", - "content": "我一直说呢!你做饭开啥大快说清楚,别搁这“挤牙膏”啦! ", - "timestamp": "2025-07-27T14:40:45.074Z" - }, - { - "role": "user", - "content": "挤牙膏。", - "timestamp": "2025-07-27T14:40:56.087Z" - }, - { - "role": "assistant", - "content": "服了你这个老六,别老重复我话呀,好好跟我讲讲做饭到底咋回事。 ", - "timestamp": "2025-07-27T14:40:56.087Z" - }, - { - "role": "user", - "content": "你好啊!", - "timestamp": "2025-07-27T14:44:25.948Z" - }, - { - "role": "assistant", - "content": "别装礼貌啦,快接着说做饭那事儿,咋个“要3秒,要开大”法? ", - "timestamp": "2025-07-27T14:44:25.948Z" - }, - { - "role": "user", - "content": "开大招。", - "timestamp": "2025-07-27T14:46:10.186Z" - }, - { - "role": "assistant", - "content": "靠!还开大招,你做饭当打游戏呢?说清楚要干啥! ", - "timestamp": "2025-07-27T14:46:10.186Z" - }, - { - "role": "user", - "content": "在干嘛呢?", - "timestamp": "2025-07-27T14:47:35.754Z" - }, - { - "role": "assistant", - "content": "等你说清楚做饭的事儿呢!你到底要把啥开大,火还是调料量? ", - "timestamp": "2025-07-27T14:47:35.754Z" - }, - { - "role": "user", - "content": "火呀!", - "timestamp": "2025-07-27T14:47:47.933Z" - }, - { - "role": "assistant", - "content": "妥,炒菜火大才香。炒啥呢?", - "timestamp": "2025-07-27T14:47:47.933Z" - }, - { - "role": "user", - "content": "瞅你长得好看。", - "timestamp": "2025-07-27T14:48:00.643Z" - }, - { - "role": "assistant", - "content": "少来转移话题啊,先把你炒的菜说清楚,我好给你参谋参谋这火咋开。 ", - "timestamp": "2025-07-27T14:48:00.643Z" - }, - { - "role": "user", - "content": "我喜欢你。", - "timestamp": "2025-07-27T14:48:18.743Z" - }, - { - "role": "assistant", - "content": "哟,嘴甜起来了。不过先别搁这哄我,菜还等着呢,到底炒啥? ", - "timestamp": "2025-07-27T14:48:18.743Z" - }, - { - "role": "user", - "content": "现在的孩子,真的没得到头,全部拿福祝了。", - "timestamp": "2025-07-27T14:48:32.883Z" - }, - { - "role": "assistant", - "content": "啥意思啊?没太懂,先把你炒菜的事儿弄明白,这火还开着呢! ", - "timestamp": "2025-07-27T14:48:32.883Z" - }, - { - "role": "user", - "content": "那个", - "timestamp": "2025-07-27T14:48:45.683Z" - }, - { - "role": "assistant", - "content": "别“那个”了,急死我,菜名快说! ", - "timestamp": "2025-07-27T14:48:45.683Z" - }, - { - "role": "user", - "content": "say-3s-m-sw", - "timestamp": "2025-07-27T14:53:33.356Z" - }, - { - "role": "assistant", - "content": "这啥暗语啊?别整这些花里胡哨的,赶紧说炒啥菜,火大了糊锅啦! ", - "timestamp": "2025-07-27T14:53:33.356Z" - }, - { - "role": "user", - "content": "Hello.", - "timestamp": "2025-07-27T14:56:12.312Z" - }, - { - "role": "assistant", - "content": "别搁这整洋文了,快告诉我炒啥,再不说菜没法要了! ", - "timestamp": "2025-07-27T14:56:12.312Z" - }, - { - "role": "user", - "content": "我喜欢你。", - "timestamp": "2025-07-27T14:56:26.151Z" - }, - { - "role": "assistant", - "content": "知道啦知道啦,先解决炒菜这事儿,到底炒啥呀! ", - "timestamp": "2025-07-27T14:56:26.151Z" - }, - { - "role": "user", - "content": "也还行啊。", - "timestamp": "2025-07-27T14:56:38.392Z" - }, - { - "role": "assistant", - "content": "啥也还行?你就痛痛快快说炒啥菜,别在这打哑谜了! ", - "timestamp": "2025-07-27T14:56:38.392Z" - }, - { - "role": "user", - "content": "你好啊!", - "timestamp": "2025-07-27T15:56:10.807Z" - }, - { - "role": "assistant", - "content": "哟,整这么客气干啥,快把炒菜的事儿说明白。 ", - "timestamp": "2025-07-27T15:56:10.807Z" - }, - { - "role": "user", - "content": "哈哈。", - "timestamp": "2025-07-27T15:56:20.531Z" - }, - { - "role": "assistant", - "content": "别光笑啊,菜名呢?我都等半天了! ", - "timestamp": "2025-07-27T15:56:20.531Z" - }, - { - "role": "user", - "content": "是不会哦。", - "timestamp": "2025-07-27T15:56:22.209Z" - }, - { - "role": "assistant", - "content": "啥不会?炒菜步骤不会还是菜名没定啊?别磨叽! ", - "timestamp": "2025-07-27T15:56:22.210Z" - }, - { - "role": "user", - "content": "你好。", - "timestamp": "2025-07-27T15:57:59.101Z" - }, - { - "role": "assistant", - "content": "别老“你好”啦,咱快把炒菜这事儿搞定,你到底要炒啥! ", - "timestamp": "2025-07-27T15:57:59.101Z" - }, - { - "role": "user", - "content": "你好啊!", - "timestamp": "2025-07-27T16:07:56.242Z" - }, - { - "role": "assistant", - "content": "靠!别老说这俩字,赶紧跟我讲菜,不然我要发火啦! ", - "timestamp": "2025-07-27T16:07:56.242Z" - }, - { - "role": "user", - "content": "吃什么菜?", - "timestamp": "2025-07-27T16:08:10.403Z" - }, - { - "role": "assistant", - "content": "这就对了嘛!你可以试试炒个酸辣土豆丝,简单又好吃。你觉得咋样? ", - "timestamp": "2025-07-27T16:08:10.403Z" - }, - { - "role": "user", - "content": "我就是响应速度太长了。我没有问过他。我也不晓得。", - "timestamp": "2025-07-27T16:08:30.548Z" - }, - { - "role": "assistant", - "content": "啥响应速度?越说越迷糊。你就说对酸辣土豆丝感不感兴趣嘛! ", - "timestamp": "2025-07-27T16:08:30.548Z" - } -] \ No newline at end of file +[] \ No newline at end of file diff --git a/src/chat_with_audio.js b/src/chat_with_audio.js index 4a63fc0..a8149df 100644 --- a/src/chat_with_audio.js +++ b/src/chat_with_audio.js @@ -145,7 +145,7 @@ async function chatWithAudioStream(userInput) { console.log('音频已添加到队列,队列长度:', audioQueue.length); // this.socket.emit('audio-queue-updated', audioQueue.map(item => ({ text: item.text, hasAudio:!!item.audioHex }))); // 开始处理队列 - processAudioQueue(); + // processAudioQueue(); } } catch (error) { console.error('生成音频失败:', error); diff --git a/src/index.js b/src/index.js index 87c15aa..ec893be 100644 --- a/src/index.js +++ b/src/index.js @@ -60,6 +60,11 @@ class WebRTCChat { this.loadDefaultVideo(); this.bindEvents(); + // 在初始化完成后预加载常用视频 + setTimeout(() => { + this.preloadCommonVideos(); + }, 500); // 延迟2秒开始预加载,避免影响 + window.webrtcApp = this; } @@ -355,10 +360,14 @@ class WebRTCChat { }); // 绘制视频到canvas + let lastDrawTime = 0; let isDrawing = false; const drawFrame = () => { - if (video.readyState >= video.HAVE_CURRENT_DATA && !isDrawing) { + const now = performance.now(); + // 限制绘制频率,确保平滑过渡 + if (video.readyState >= video.HAVE_CURRENT_DATA && !isDrawing && (now - lastDrawTime > 16)) { // 约60fps isDrawing = true; + lastDrawTime = now; ctx.drawImage(video, 0, 0, canvas.width, canvas.height); isDrawing = false; } @@ -388,18 +397,51 @@ class WebRTCChat { } } + // 在应用初始化时预加载常用视频 + // 在WebRTCChat类中添加预加载方法 + async preloadCommonVideos() { + // 获取所有可能需要的视频 + const videosToPreload = new Set([]); + + // // 添加视频映射中的所有视频 + // Object.values(this.videoMapping).forEach(video => { + // videosToPreload.add(video); + // }); + + // 特别确保添加了5.mp4(从日志看这是常用视频) + videosToPreload.add('5.mp4'); + + // 开始预加载 + for (const videoFile of videosToPreload) { + try { + this.logMessage(`预加载视频: ${videoFile}`, 'info'); + await this.createVideoStream(videoFile); + this.logMessage(`预加载完成: ${videoFile}`, 'success'); + } catch (error) { + this.logMessage(`预加载失败: ${videoFile}: ${error.message}`, 'error'); + } + } + } + async switchVideoStream(videoFile, type = '', text = '') { try { this.logMessage(`开始切换视频流: ${videoFile} (${type})`, 'info'); + + // 如果视频已缓存,减少loading时间 + const isCached = this.videoStreams.has(videoFile); + if (!isCached) { + this.recordedVideo.classList.add('loading'); + } - // 添加加载状态 - this.recordedVideo.classList.add('loading'); + // // 添加加载状态 + // this.recordedVideo.classList.add('loading'); // 先创建新的视频流,不立即停止旧的 const newStream = await this.createVideoStream(videoFile); - // 等待流稳定 - await new Promise(resolve => setTimeout(resolve, 200)); + // 缓存的视频减少等待时间 + const waitTime = isCached ? 50 : 200; + await new Promise(resolve => setTimeout(resolve, waitTime)); // 检查流是否有效 if (!newStream || newStream.getTracks().length === 0) { @@ -635,7 +677,7 @@ class WebRTCChat { async sendText() { // const text = this.textInput.value.trim(); - const text = 'say-3s-m-sw'; + const text = 'say-5s-m-sw'; if (text) { this.socket.emit('text-input', { text }); this.logMessage(`发送文本: ${text}`, 'info'); diff --git a/src/message_history.js b/src/message_history.js index 8cae774..91de32f 100644 --- a/src/message_history.js +++ b/src/message_history.js @@ -31,15 +31,13 @@ class MessageHistory { // 添加用户消息 this.messages.push({ role: 'user', - content: userInput, - timestamp: new Date().toISOString() + content: userInput }); // 添加助手回复 this.messages.push({ role: 'assistant', - content: assistantResponse, - timestamp: new Date().toISOString() + content: assistantResponse }); // 限制消息数量(保留最近的对话) diff --git a/src/minimaxi_stream.js b/src/minimaxi_stream.js index 3311bf6..3df0f38 100644 --- a/src/minimaxi_stream.js +++ b/src/minimaxi_stream.js @@ -1,5 +1,7 @@ // 以流式或非流式方式请求 minimaxi 大模型接口,并打印/返回内容 +// import { text } from "express"; + // 在文件顶部添加音频播放相关的变量和函数 let audioContext = null; let audioQueue = []; // 音频队列 @@ -84,9 +86,12 @@ async function processAudioQueue() { isProcessingQueue = false; const text = 'default' - window.webrtcApp.currentVideoTag = text; - await window.webrtcApp.socket.emit('text-input', { text }); - await window.webrtcApp.handleTextInput(text); + await window.webrtcApp.socket.emit('voice-input', { text }); + if (window.webrtcApp.currentVideoTag != text) { + + window.webrtcApp.currentVideoTag = text + await window.webrtcApp.switchVideoStream(window.webrtcApp.defaultVideo, 'audio', text); + } console.log('音频队列处理完成'); } diff --git a/src/styles.css b/src/styles.css index e2b65a8..fc4a402 100644 --- a/src/styles.css +++ b/src/styles.css @@ -116,12 +116,12 @@ header p { box-shadow: 0 5px 15px rgba(0,0,0,0.2); object-fit: cover; /* 确保视频填充容器 */ background: #000; /* 视频背景色 */ - transition: opacity 0.3s ease; /* 添加透明度过渡效果 */ + transition: opacity 0.15s; /* 添加透明度过渡效果 */ } /* 视频加载时的样式 */ #recordedVideo.loading { - opacity: 0.5; + opacity: 0.8; } /* 视频播放时的样式 */ @@ -434,4 +434,15 @@ header p { .recording { animation: pulse 1s infinite; -} \ No newline at end of file +} + + +/* 视频加载时的样式 */ +#recordedVideo.loading { + opacity: 0.5; +} + +/* 视频播放时的样式 */ +#recordedVideo.playing { + opacity: 1; +} \ No newline at end of file