From 9f58286bfeda0cae69c526aa395e614cb2b014d6 Mon Sep 17 00:00:00 2001 From: fsy Date: Fri, 21 Mar 2025 17:52:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=E8=AF=9D=E8=83=BD=E5=A4=9F=E5=9C=A8?= =?UTF-8?q?=E4=B8=A4=E8=BE=B9=E6=98=BE=E7=A4=BA=EF=BC=8C=E8=BF=98=E7=BC=BA?= =?UTF-8?q?=E5=B0=91ui=E4=BC=98=E5=8C=96=E5=92=8C=E9=95=BFjson=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/services/agora.js | 60 +++++++++++++++++++++++++--- src/services/api.js | 33 ++------------- src/stores/chat.js | 93 ++++++++++++++++++++++++++----------------- 3 files changed, 115 insertions(+), 71 deletions(-) diff --git a/src/services/agora.js b/src/services/agora.js index f492927..f6c971f 100644 --- a/src/services/agora.js +++ b/src/services/agora.js @@ -10,8 +10,8 @@ class AgoraService { this.volumeIndicator = null; // 加入同一RTC频道 this.appid = '01a1debc964a4c6a8df1de2a6ce7aa4d'; - this.token = '007eJxTYChiW7ib6cSzPW7fP2xqFVvPqf854sNXniin39cd3pu931SlwGBgmGiYkpqUbGlmkmiSbJZokZIG5BslmiWnmicmmqRcenA7vSGQkaFhbQArIwMEgvgiDMn5eWWJmUCyOD8nNd7QwtDAxJyBAQDAkSkW'; - this.channel = 'convaiconsole_181047'; + this.token = '007eJxTYOhQ/af5fwa3YP9mzYq4WWxKco1TJJqEC9L6z39c0cf2xkuBwcAw0TAlNSnZ0swk0STZLNEiJQ3IN0o0S041T0w0SQk0u5veEMjIwFi9lhFIgiGIL8KQnJ9XlpgJJIvzc1LjDQ3NjE3MGRgACCIjzA=='; + this.channel = 'convaiconsole_116347'; this.isListening = false; // 是否正在监听 this.isSpeaking = false; // 用户是否正在说话 @@ -19,6 +19,7 @@ class AgoraService { this.recordedChunks = []; // 存储录制的语音段 this.inConversation = false; // 是否在对话状态中 this.speechSegmentCallback = null; // 语音段落回调函数 + this.readableTextCallback = null; // 可读文本回调函数 } /** @@ -35,6 +36,52 @@ class AgoraService { * Set up event listeners for the Agora client */ setupEventListeners() { + let jsonBuffer = ''; + + this.client.on('stream-message', (uid, message) => { + try { + // 确认接收到的是字节流(Uint8Array) + if (message instanceof Uint8Array) { + const decodedMessage = new TextDecoder().decode(message); + // console.log('Decoded message (Raw String):', decodedMessage); + + const parts = decodedMessage.split('|'); + const base64Data = parts[parts.length - 1]; + // console.log('Extracted Base64 data:', base64Data); + + const jsonString = atob(base64Data); + console.log('Decoded JSON string:', jsonString); + + jsonBuffer += jsonString; + if (isCompleteJson(jsonBuffer)) { + const jsonData = JSON.parse(jsonString); // 将字符串解析为 JSON 对象 + console.log('Parsed JSON object:', jsonData); + + if (this.readableTextCallback && typeof this.readableTextCallback === 'function') { + this.readableTextCallback(jsonData.text); // 传递解码后的文本到回调 + } + jsonBuffer = ''; + + return jsonData.text; + } + + } else { + console.log('Received message is not Uint8Array:', message); + } + } catch (error) { + console.error('Error processing stream-message:', error); + } + }); + + function isCompleteJson(jsonString) { + try { + JSON.parse(jsonString); // 解析测试是否为合法 JSON + return true; // 如果能被解析,说明是完整的 JSON + } catch (error) { + return false; // 捕获解析错误,说明 JSON 不完整 + } + } + this.client.on('user-published', async (user, mediaType) => { await this.client.subscribe(user, mediaType); if (mediaType === 'audio') { @@ -164,11 +211,13 @@ class AgoraService { /** * 开始对话状态 - * @param {Function} callback - 语音段落回调函数 + * @param {Function} speechCallback - 语音段落回调函数 + * @param {Function} textCallback - 可读文本回调函数 */ - startConversation(callback) { + startConversation(speechCallback, textCallback) { this.inConversation = true; - this.speechSegmentCallback = callback; + this.speechSegmentCallback = speechCallback; + this.readableTextCallback = textCallback; } /** @@ -177,6 +226,7 @@ class AgoraService { endConversation() { this.inConversation = false; this.speechSegmentCallback = null; + this.readableTextCallback = null; // 如果有正在处理的语音段,发送它 if (this.segmentBuffer && this.segmentBuffer.trim()) { diff --git a/src/services/api.js b/src/services/api.js index 6515a0e..facdda5 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -35,10 +35,10 @@ class ApiService { const response = await this.client.post( `${this.baseUrl}/projects/${this.projectId}/join/`, { - "name": "convaiconsole_181047", + "name": "convaiconsole_116347", "properties": { - "channel": "convaiconsole_181047", - "agent_rtc_uid": "28794", + "channel": "convaiconsole_116347", + "agent_rtc_uid": "87578", "remote_rtc_uids": [ "*" ], @@ -93,7 +93,7 @@ class ApiService { "enable_metrics": true, "audio_scenario": "default" }, - "token": "007eJxTYChiW7ib6cSzPW7fP2xqFVvPqf854sNXniin39cd3pu931SlwGBgmGiYkpqUbGlmkmiSbJZokZIG5BslmiWnmicmmqRcenA7vSGQkaFhbQArIwMEgvgiDMn5eWWJmUCyOD8nNd7QwtDAxJyBAQDAkSkW", + "token": "007eJxTYOhQ/af5fwa3YP9mzYq4WWxKco1TJJqEC9L6z39c0cf2xkuBwcAw0TAlNSnZ0swk0STZLNEiJQ3IN0o0S041T0w0SQk0u5veEMjIwFi9lhFIgiGIL8KQnJ9XlpgJJIvzc1LjDQ3NjE3MGRgACCIjzA==", "advanced_features": { "enable_aivad": false } @@ -109,31 +109,6 @@ class ApiService { } } - /** - * Send a message to the AI agent - * @param {string} message - The message to send - * @returns {Promise} - The response from the API - */ - async sendMessage(message) { - if (!this.sessionId) { - throw new Error('No active session. Please join a project first.'); - } - - try { - const response = await this.client.post( - `${this.baseUrl}/sessions/${this.sessionId}/messages/`, - { - type: 'text', - content: message - } - ); - return response.data; - } catch (error) { - console.error('Error sending message:', error); - throw error; - } - } - /** * End the current session * @returns {Promise} - The response from the API diff --git a/src/stores/chat.js b/src/stores/chat.js index 6bf89e1..716e886 100644 --- a/src/stores/chat.js +++ b/src/stores/chat.js @@ -47,13 +47,11 @@ export const useChatStore = defineStore('chat', { const status =response.status; await agoraService.join(agent_id, create_ts, status) - // await agoraService.join(token, channel, agentRtcUid); this.isConnected = true; this.error = null; // Add greeting message - // const greetingMessage = response.properties.llm.greeting_message; const greetingMessage = "你好呀,有什么可以帮您?"; if (greetingMessage) { this.addMessage({ @@ -82,8 +80,11 @@ export const useChatStore = defineStore('chat', { this.isListening = true; this.currentTranscript = ''; - // 设置语音段落回调 - agoraService.startConversation(this.handleSpeechSegment.bind(this)); + // 设置语音段落回调和可读文本回调 + agoraService.startConversation( + this.handleSpeechSegment.bind(this), + this.handleReadableText.bind(this) + ); // 启动音频发布 if (!agoraService.localAudioTrack) { @@ -95,6 +96,22 @@ export const useChatStore = defineStore('chat', { return true; }, + + /** + * 处理可读文本 + * @param {string} text - 从Agora获取的可读文本 + */ + handleReadableText(text) { + if (!text || !text.trim()) return; + const isFromAI = text.includes('\n\n') || text.includes('\n'); + + this.addMessage({ + id: Date.now(), + content: text, + sender: isFromAI ? 'ai' : 'user', + timestamp: new Date().toISOString(), + }); + }, /** * 结束对话状态,停止持续监听 @@ -159,6 +176,8 @@ export const useChatStore = defineStore('chat', { * @param {string} text - 语音段落文本 */ handleSpeechSegment(text) { + + console.log("我在这里!"); if (!text || !text.trim()) return; // 更新当前转写 @@ -202,44 +221,44 @@ export const useChatStore = defineStore('chat', { * Send a message to the AI * @param {string} content - The message content */ - async sendMessage(content) { - try { - this.isProcessing = true; + // async sendMessage(content) { + // try { + // this.isProcessing = true; - console.log("user send content:",content); - // Add user message to the list - this.addMessage({ - id: Date.now(), - content: content, - sender: 'user', - timestamp: new Date().toISOString(), - }); + // console.log("user send content:",content); + // // Add user message to the list + // this.addMessage({ + // id: Date.now(), + // content: content, + // sender: 'user', + // timestamp: new Date().toISOString(), + // }); - // Send message to API - const response = await apiService.sendMessage(content); + // // Send message to API + // const response = await apiService.sendMessage(content); - // 检查response返回的内容 - console.log("AI response:",response); + // // 检查response返回的内容 + // console.log("AI response:",response); - // Add AI response to the list - if (response && response.content) { - this.addMessage({ - id: Date.now(), - content: response.content, - sender: 'ai', - timestamp: new Date().toISOString(), - }); - } + // // Add AI response to the list + // if (response && response.content) { + // this.addMessage({ + // id: Date.now(), + // content: response.content, + // sender: 'ai', + // timestamp: new Date().toISOString(), + // }); + // } - this.isProcessing = false; - return true; - } catch (error) { - this.error = error.message || 'Failed to send message'; - this.isProcessing = false; - console.error('Error sending message:', error); - return false; - } - }, + // this.isProcessing = false; + // return true; + // } catch (error) { + // this.error = error.message || 'Failed to send message'; + // this.isProcessing = false; + // console.error('Error sending message:', error); + // return false; + // } + // }, /** * Add a message to the list