news 2026/7/27 7:00:09

ChatGPT桌面版语音控制AI智能体开发实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ChatGPT桌面版语音控制AI智能体开发实战指南

ChatGPT 桌面版语音控制 AI 智能体完整开发指南

在AI技术快速发展的今天,将语音交互与AI智能体结合已成为提升用户体验的重要方向。许多开发者在尝试为ChatGPT构建桌面应用时,常常面临语音集成复杂、API调用不稳定、界面交互不流畅等问题。本文将从零开始,完整演示如何构建一个支持语音控制的ChatGPT桌面版AI智能体应用。

本文将涵盖从环境搭建、语音识别集成、ChatGPT API调用到桌面应用封装的完整流程,提供可运行的代码示例和常见问题解决方案。无论你是前端开发者想要学习桌面应用开发,还是AI爱好者希望打造个性化智能助手,都能从中获得实用价值。

1. 语音控制AI智能体的核心概念与技术栈

1.1 什么是AI智能体

AI智能体(AI Agent)是指能够感知环境、进行决策并执行行动的智能系统。在本文的语境中,我们构建的AI智能体特指能够通过语音与用户交互、理解自然语言指令并给出智能响应的桌面应用程序。

与传统聊天机器人不同,AI智能体通常具备以下特征:

  • 自主性:能够独立完成特定任务
  • 交互性:支持多模态交互(语音、文本等)
  • 学习能力:可以基于交互历史优化响应
  • 任务导向:能够理解并执行复杂指令

1.2 技术架构概述

构建语音控制的ChatGPT桌面应用需要整合多个技术组件:

语音输入 → 语音识别 → 文本处理 → ChatGPT API → 响应生成 → 语音合成 → 音频输出

核心技术栈包括:

  • 桌面应用框架:Electron或Tauri
  • 语音识别:Web Speech API或第三方语音服务
  • AI对话引擎:ChatGPT API(GPT-3.5/GPT-4)
  • 语音合成:Web Speech API的语音合成功能
  • 前端技术:HTML/CSS/JavaScript

1.3 开发环境要求

在开始编码前,需要准备以下开发环境:

操作系统支持

  • Windows 10/11(推荐)
  • macOS 10.14+
  • Linux Ubuntu 18.04+

开发工具

  • Node.js 16.0+
  • npm 8.0+ 或 yarn 1.22+
  • 代码编辑器(VS Code推荐)
  • Git版本控制

API依赖

  • OpenAI API密钥
  • 稳定的网络连接

2. 项目环境搭建与基础配置

2.1 创建Electron项目基础结构

首先创建项目目录并初始化package.json:

# 创建项目目录 mkdir chatgpt-desktop-agent cd chatgpt-desktop-agent # 初始化npm项目 npm init -y # 安装Electron依赖 npm install --save-dev electron npm install --save-dev electron-builder

配置package.json中的主要脚本和基本信息:

{ "name": "chatgpt-desktop-agent", "version": "1.0.0", "description": "语音控制的ChatGPT桌面AI智能体", "main": "main.js", "scripts": { "start": "electron .", "build": "electron-builder", "dev": "electron . --dev" }, "author": "Your Name", "license": "MIT", "devDependencies": { "electron": "^22.0.0", "electron-builder": "^24.0.0" } }

2.2 配置主进程文件

创建主进程文件main.js,这是Electron应用的入口点:

const { app, BrowserWindow, ipcMain } = require('electron'); const path = require('path'); // 保持对窗口对象的全局引用 let mainWindow; function createWindow() { // 创建浏览器窗口 mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: true, contextIsolation: false, enableRemoteModule: true }, icon: path.join(__dirname, 'assets/icon.png'), // 应用图标 title: 'ChatGPT桌面AI智能体' }); // 加载应用的index.html mainWindow.loadFile('src/index.html'); // 开发模式下打开开发者工具 if (process.argv.includes('--dev')) { mainWindow.webContents.openDevTools(); } // 当窗口被关闭时发出信号 mainWindow.on('closed', () => { mainWindow = null; }); } // Electron初始化完成时调用 app.whenReady().then(createWindow); // 所有窗口关闭时退出应用(macOS除外) app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } }); app.on('activate', () => { // macOS中点击dock图标时重新创建窗口 if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } }); // 处理来自渲染进程的消息 ipcMain.handle('get-api-key', () => { // 在实际应用中应从安全存储中读取 return process.env.OPENAI_API_KEY; });

2.3 项目目录结构规划

建立清晰的项目目录结构有助于代码维护:

chatgpt-desktop-agent/ ├── main.js # Electron主进程 ├── package.json # 项目配置 ├── src/ # 源代码目录 │ ├── index.html # 主界面 │ ├── renderer.js # 渲染进程逻辑 │ ├── styles/ # 样式文件 │ │ └── main.css │ └── assets/ # 静态资源 │ └── icons/ ├── config/ # 配置文件 │ └── api-config.js └── build/ # 构建输出

3. 语音识别模块实现

3.1 Web Speech API集成

Web Speech API提供了原生的语音识别能力,无需额外依赖:

// src/voice-recognition.js class VoiceRecognition { constructor() { this.recognition = null; this.isListening = false; this.finalTranscript = ''; this.initSpeechRecognition(); } initSpeechRecognition() { // 检查浏览器支持情况 if (!('webkitSpeechRecognition' in window) && !('SpeechRecognition' in window)) { throw new Error('该浏览器不支持语音识别功能'); } const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; this.recognition = new SpeechRecognition(); // 配置识别参数 this.recognition.continuous = true; this.recognition.interimResults = true; this.recognition.lang = 'zh-CN'; // 设置中文识别 // 绑定事件处理 this.recognition.onstart = this.onStart.bind(this); this.recognition.onresult = this.onResult.bind(this); this.recognition.onerror = this.onError.bind(this); this.recognition.onend = this.onEnd.bind(this); } onStart() { this.isListening = true; this.finalTranscript = ''; console.log('语音识别开始'); this.dispatchEvent('listeningStart'); } onResult(event) { let interimTranscript = ''; for (let i = event.resultIndex; i < event.results.length; i++) { const transcript = event.results[i][0].transcript; if (event.results[i].isFinal) { this.finalTranscript += transcript; } else { interimTranscript += transcript; } } this.dispatchEvent('interimResult', { interimTranscript, finalTranscript: this.finalTranscript }); } onError(event) { console.error('语音识别错误:', event.error); this.dispatchEvent('error', event.error); } onEnd() { this.isListening = false; console.log('语音识别结束'); this.dispatchEvent('listeningEnd', this.finalTranscript); // 自动重新开始监听(连续模式) if (this.autoRestart) { setTimeout(() => this.start(), 100); } } start() { if (this.recognition && !this.isListening) { try { this.recognition.start(); } catch (error) { console.error('启动语音识别失败:', error); } } } stop() { if (this.recognition && this.isListening) { this.recognition.stop(); } } // 事件系统 addEventListener(event, callback) { if (!this.eventListeners) { this.eventListeners = {}; } if (!this.eventListeners[event]) { this.eventListeners[event] = []; } this.eventListeners[event].push(callback); } dispatchEvent(event, data) { if (this.eventListeners && this.eventListeners[event]) { this.eventListeners[event].forEach(callback => callback(data)); } } }

3.2 语音识别界面组件

创建用户友好的语音控制界面:

<!-- src/voice-control.html --> <div class="voice-control-container"> <div class="voice-status"> <div id="voiceIndicator" class="voice-indicator inactive"> <div class="pulse-ring"></div> <div class="mic-icon"> <svg width="24" height="24" viewBox="0 0 24 24"> <path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3z"/> <path d="M17 11c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z"/> </svg> </div> </div> <div class="status-text" id="statusText">点击开始语音对话</div> </div> <div class="voice-transcript"> <div class="interim-transcript" id="interimTranscript"></div> <div class="final-transcript" id="finalTranscript"></div> </div> <div class="control-buttons"> <button id="startListening" class="btn btn-primary">开始聆听</button> <button id="stopListening" class="btn btn-secondary" disabled>停止聆听</button> <button id="clearTranscript" class="btn btn-outline">清空记录</button> </div> </div>

对应的CSS样式:

/* src/styles/voice-control.css */ .voice-control-container { padding: 20px; text-align: center; background: #f5f5f5; border-radius: 10px; margin: 20px 0; } .voice-status { margin-bottom: 20px; } .voice-indicator { width: 80px; height: 80px; border-radius: 50%; margin: 0 auto 10px; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; position: relative; } .voice-indicator.inactive { background: #e0e0e0; border: 3px solid #bdbdbd; } .voice-indicator.listening { background: #4caf50; border: 3px solid #2e7d32; animation: pulse 1.5s infinite; } .voice-indicator.error { background: #f44336; border: 3px solid #c62828; } .pulse-ring { position: absolute; width: 100%; height: 100%; border-radius: 50%; opacity: 0; border: 2px solid; } .voice-indicator.listening .pulse-ring { animation: sonar 1.5s infinite; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } @keyframes sonar { 0% { transform: scale(1); opacity: 0.8; } 100% { transform: scale(1.5); opacity: 0; } } .status-text { font-size: 16px; color: #666; margin-top: 10px; } .voice-transcript { background: white; border-radius: 8px; padding: 15px; margin: 15px 0; min-height: 100px; text-align: left; } .interim-transcript { color: #666; font-style: italic; margin-bottom: 10px; } .final-transcript { color: #333; font-weight: 500; } .control-buttons { display: flex; gap: 10px; justify-content: center; } .btn { padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 14px; transition: all 0.3s ease; } .btn-primary { background: #2196f3; color: white; } .btn-primary:hover:not(:disabled) { background: #1976d2; } .btn-secondary { background: #ff9800; color: white; } .btn-secondary:hover:not(:disabled) { background: #f57c00; } .btn-outline { background: transparent; border: 1px solid #666; color: #666; } .btn:disabled { opacity: 0.6; cursor: not-allowed; }

4. ChatGPT API集成与对话管理

4.1 API客户端封装

创建专门的ChatGPT API客户端类:

// src/chatgpt-client.js class ChatGPTClient { constructor(apiKey) { this.apiKey = apiKey; this.baseURL = 'https://api.openai.com/v1'; this.conversationHistory = []; this.maxHistoryLength = 10; // 保持最近10轮对话 } async sendMessage(message, options = {}) { const { model = 'gpt-3.5-turbo', temperature = 0.7, maxTokens = 1000 } = options; // 构建对话历史 const messages = this.buildMessageHistory(message); try { const response = await fetch(`${this.baseURL}/chat/completions`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}` }, body: JSON.stringify({ model, messages, temperature, max_tokens: maxTokens, stream: false }) }); if (!response.ok) { const errorData = await response.json(); throw new Error(`API请求失败: ${errorData.error?.message || response.statusText}`); } const data = await response.json(); const assistantMessage = data.choices[0].message.content; // 更新对话历史 this.updateConversationHistory('assistant', assistantMessage); return { success: true, message: assistantMessage, usage: data.usage }; } catch (error) { console.error('ChatGPT API调用错误:', error); return { success: false, error: error.message }; } } buildMessageHistory(newMessage) { // 添加系统提示词 const messages = [ { role: 'system', content: '你是一个有帮助的AI助手。请用简洁明了的中文回答用户问题,保持友好和专业的语气。' } ]; // 添加历史对话 messages.push(...this.conversationHistory); // 添加新消息 messages.push({ role: 'user', content: newMessage }); return messages; } updateConversationHistory(role, content) { this.conversationHistory.push({ role, content }); // 限制历史记录长度 if (this.conversationHistory.length > this.maxHistoryLength * 2) { this.conversationHistory = this.conversationHistory.slice(-this.maxHistoryLength * 2); } } clearHistory() { this.conversationHistory = []; } // 流式传输支持(可选) async* sendMessageStream(message, options = {}) { const messages = this.buildMessageHistory(message); const response = await fetch(`${this.baseURL}/chat/completions`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}` }, body: JSON.stringify({ ...options, messages, stream: true }) }); if (!response.ok) { throw new Error(`API请求失败: ${response.statusText}`); } const reader = response.body.getReader(); const decoder = new TextDecoder(); try { while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); const lines = chunk.split('\n'); for (const line of lines) { if (line.startsWith('data: ') && !line.includes('[DONE]')) { try { const data = JSON.parse(line.slice(6)); const content = data.choices[0]?.delta?.content; if (content) { yield content; } } catch (e) { // 忽略解析错误 } } } } } finally { reader.releaseLock(); } } }

4.2 对话界面实现

创建主要的聊天界面组件:

<!-- src/chat-interface.html --> <div class="chat-container"> <div class="chat-header"> <h2>ChatGPT桌面AI助手</h2> <div class="connection-status"> <span id="apiStatus" class="status-indicator">API状态: 检查中...</span> </div> </div> <div class="chat-messages" id="chatMessages"> <div class="message system-message"> <div class="message-content"> 欢迎使用语音控制的ChatGPT桌面助手!点击下方麦克风按钮开始语音对话。 </div> </div> </div> <div class="chat-input-area"> <div class="input-group"> <textarea id="textInput" placeholder="输入您的问题或使用语音输入..." rows="3"></textarea> <div class="input-buttons"> <button id="sendText" class="btn btn-primary">发送</button> <button id="voiceToggle" class="btn btn-voice"> <svg width="20" height="20" viewBox="0 0 24 24"> <path fill="currentColor" d="M12 2a3 3 0 0 1 3 3v6a3 3 0 0 1-6 0V5a3 3 0 0 1 3-3z"/> <path fill="currentColor" d="M19 10v1a7 7 0 0 1-14 0v-1a1 1 0 1 1 2 0v1a5 5 0 0 0 10 0v-1a1 1 0 1 1 2 0z"/> <path fill="currentColor" d="M12 18a1 1 0 0 1-1-1v-2a1 1 0 1 1 2 0v2a1 1 0 0 1-1 1z"/> </svg> </button> </div> </div> </div> </div>

对应的样式设计:

/* src/styles/chat-interface.css */ .chat-container { display: flex; flex-direction: column; height: 100vh; background: #ffffff; } .chat-header { background: #1976d2; color: white; padding: 15px 20px; display: flex; justify-content: space-between; align-items: center; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .chat-header h2 { margin: 0; font-size: 1.5em; } .status-indicator { font-size: 0.9em; padding: 5px 10px; border-radius: 15px; background: rgba(255,255,255,0.2); } .chat-messages { flex: 1; overflow-y: auto; padding: 20px; background: #fafafa; } .message { margin-bottom: 15px; display: flex; } .message.user-message { justify-content: flex-end; } .message.assistant-message { justify-content: flex-start; } .message.system-message { justify-content: center; } .message-content { max-width: 70%; padding: 12px 16px; border-radius: 18px; word-wrap: break-word; } .user-message .message-content { background: #1976d2; color: white; } .assistant-message .message-content { background: #e3f2fd; color: #333; border: 1px solid #bbdefb; } .system-message .message-content { background: #f5f5f5; color: #666; font-style: italic; font-size: 0.9em; } .chat-input-area { padding: 20px; background: white; border-top: 1px solid #e0e0e0; } .input-group { display: flex; gap: 10px; align-items: flex-end; } .input-group textarea { flex: 1; padding: 12px; border: 1px solid #ddd; border-radius: 8px; resize: vertical; font-family: inherit; font-size: 14px; } .input-buttons { display: flex; gap: 5px; } .btn-voice { background: #ff9800; color: white; border: none; border-radius: 50%; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; cursor: pointer; } .btn-voice.listening { animation: voice-pulse 1.5s infinite; } @keyframes voice-pulse { 0% { box-shadow: 0 0 0 0 rgba(255, 152, 0, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(255, 152, 0, 0); } 100% { box-shadow: 0 0 0 0 rgba(255, 152, 0, 0); } }

5. 语音合成与音频反馈

5.1 文本转语音实现

集成Web Speech API的语音合成功能:

// src/text-to-speech.js class TextToSpeech { constructor() { this.synthesis = window.speechSynthesis; this.isSpeaking = false; this.voice = null; this.rate = 1.0; this.pitch = 1.0; this.volume = 0.8; this.initVoices(); } initVoices() { // 语音列表加载完成后再设置默认语音 if (this.synthesis.getVoices().length > 0) { this.setDefaultVoice(); } else { this.synthesis.addEventListener('voiceschanged', () => { this.setDefaultVoice(); }); } } setDefaultVoice() { const voices = this.synthesis.getVoices(); // 优先选择中文语音 const chineseVoice = voices.find(voice => voice.lang.includes('zh') || voice.lang.includes('CN') ); this.voice = chineseVoice || voices[0]; if (!this.voice) { console.warn('未找到可用的语音'); } } speak(text, options = {}) { if (this.isSpeaking) { this.stop(); } return new Promise((resolve, reject) => { const utterance = new SpeechSynthesisUtterance(text); // 设置语音参数 utterance.voice = options.voice || this.voice; utterance.rate = options.rate || this.rate; utterance.pitch = options.pitch || this.pitch; utterance.volume = options.volume || this.volume; utterance.onstart = () => { this.isSpeaking = true; this.dispatchEvent('speechStart', text); }; utterance.onend = () => { this.isSpeaking = false; this.dispatchEvent('speechEnd', text); resolve(); }; utterance.onerror = (event) => { this.isSpeaking = false; this.dispatchEvent('speechError', event.error); reject(new Error(`语音合成错误: ${event.error}`)); }; this.synthesis.speak(utterance); }); } stop() { if (this.isSpeaking) { this.synthesis.cancel(); this.isSpeaking = false; this.dispatchEvent('speechStop'); } } getAvailableVoices() { return this.synthesis.getVoices(); } setVoice(voiceName) { const voices = this.getAvailableVoices(); const voice = voices.find(v => v.name === voiceName); if (voice) { this.voice = voice; } } // 事件系统 addEventListener(event, callback) { if (!this.eventListeners) { this.eventListeners = {}; } if (!this.eventListeners[event]) { this.eventListeners[event] = []; } this.eventListeners[event].push(callback); } dispatchEvent(event, data) { if (this.eventListeners && this.eventListeners[event]) { this.eventListeners[event].forEach(callback => callback(data)); } } }

5.2 音频反馈与交互设计

创建音频可视化反馈组件:

// src/audio-feedback.js class AudioFeedback { constructor() { this.audioContext = null; this.analyser = null; this.microphone = null; this.isVisualizing = false; this.animationId = null; this.initAudioContext(); } async initAudioContext() { try { this.audioContext = new (window.AudioContext || window.webkitAudioContext)(); await this.setupAudioNodes(); } catch (error) { console.error('音频上下文初始化失败:', error); } } async setupAudioNodes() { if (!this.audioContext) return; try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false }); this.microphone = this.audioContext.createMediaStreamSource(stream); this.analyser = this.audioContext.createAnalyser(); this.analyser.fftSize = 256; this.microphone.connect(this.analyser); } catch (error) { console.error('麦克风访问失败:', error); } } startVisualization(canvasElement) { if (!this.analyser || !canvasElement) return; this.isVisualizing = true; const canvas = canvasElement; const ctx = canvas.getContext('2d'); const bufferLength = this.analyser.frequencyBinCount; const dataArray = new Uint8Array(bufferLength); const draw = () => { if (!this.isVisualizing) return; this.animationId = requestAnimationFrame(draw); this.analyser.getByteFrequencyData(dataArray); ctx.fillStyle = 'rgb(0, 0, 0)'; ctx.fillRect(0, 0, canvas.width, canvas.height); const barWidth = (canvas.width / bufferLength) * 2.5; let barHeight; let x = 0; for (let i = 0; i < bufferLength; i++) { barHeight = dataArray[i] / 2; const hue = i * 360 / bufferLength; ctx.fillStyle = `hsl(${hue}, 100%, 50%)`; ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight); x += barWidth + 1; } }; draw(); } stopVisualization() { this.isVisualizing = false; if (this.animationId) { cancelAnimationFrame(this.animationId); } } getVolumeLevel() { if (!this.analyser) return 0; const dataArray = new Uint8Array(this.analyser.frequencyBinCount); this.analyser.getByteFrequencyData(dataArray); let sum = 0; for (const value of dataArray) { sum += value; } return sum / dataArray.length / 256; } }

6. 应用集成与主界面实现

6.1 主界面整合

将各个模块整合到主界面中:

<!-- src/index.html --> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ChatGPT桌面AI智能体</title> <link rel="stylesheet" href="styles/main.css"> <link rel="stylesheet" href="styles/chat-interface.css"> <link rel="stylesheet" href="styles/voice-control.css"> </head> <body> <div class="app-container"> <!-- 侧边栏 --> <div class="sidebar"> <div class="sidebar-header"> <h3>AI助手设置</h3> </div> <div class="sidebar-content"> <div class="setting-group"> <label>语音设置</label> <select id="voiceSelect"> <option value="">加载语音中...</option> </select> </div> <div class="setting-group"> <label>语速</label> <input type="range" id="speechRate" min="0.5" max="2" step="0.1" value="1"> <span id="rateValue">1.0</span> </div> <div class="setting-group"> <label>音调</label> <input type="range" id="speechPitch" min="0.5" max="2" step="0.1" value="1"> <span id="pitchValue">1.0</span> </div> <div class="setting-group"> <button id="clearHistory" class="btn btn-outline">清空对话历史</button> </div> </div> </div> <!-- 主内容区 --> <div class="main-content"> <!-- 聊天界面 --> <div id="chatInterface"></div> <!-- 语音控制面板 --> <div id="voiceControlPanel" class="control-panel"> <canvas id="audioVisualizer" width="300" height="100"></canvas> </div> </div> </div> <!-- API配置模态框 --> <div id="apiConfigModal" class="modal"> <div class="modal-content"> <h3>API配置</h3> <p>请输入您的OpenAI API密钥:</p> <input type="password" id="apiKeyInput" placeholder="sk-..."> <div class="modal-buttons"> <button id="saveApiKey" class="btn btn-primary">保存</button> <button id="cancelApiConfig" class="btn btn-outline">取消</button> </div> </div> </div> <script src="voice-recognition.js"></script> <script src="text-to-speech.js"></script> <script src="audio-feedback.js"></script> <script src="chatgpt-client.js"></script> <script src="renderer.js"></script> </body> </html>

6.2 主逻辑控制器

实现模块间的协调控制:

// src/renderer.js class ChatGPTDesktopApp { constructor() { this.voiceRecognition = null; this.textToSpeech = null; this.audioFeedback = null; this.chatGPTClient = null; this.isVoiceMode = false; this.initApp(); } async initApp() { try { // 初始化各个模块 await this.initModules(); // 设置事件监听 this.setupEventListeners(); // 检查API配置 this.checkApiConfiguration(); console.log('ChatGPT桌面应用初始化完成'); } catch (error) { console.error('应用初始化失败:', error); this.showError('应用初始化失败: ' + error.message); } } async initModules() { // 初始化语音识别 this.voiceRecognition = new VoiceRecognition(); // 初始化语音合成 this.textToSpeech = new TextToSpeech(); // 初始化音频反馈 this.audioFeedback = new AudioFeedback(); // 等待语音加载完成 await new Promise(resolve => { if (speechSynthesis.getVoices().length > 0) { resolve(); } else { speechSynthesis.addEventListener('voiceschanged', resolve, { once: true }); } }); this.populateVoiceOptions(); } populateVoiceOptions() { const voiceSelect = document.getElementById('voiceSelect'); const voices = this.textToSpeech.getAvailableVoices(); voiceSelect.innerHTML = ''; voices.forEach(voice => { const option = document.createElement('option'); option.value = voice.name; option.textContent = `${voice.name} (${voice.lang})`; voiceSelect.appendChild(option); }); // 设置默认中文语音 const chineseVoice = voices.find(voice => voice.lang.includes('zh')); if (chineseVoice) { voiceSelect.value = chineseVoice.name; this.textToSpeech.setVoice(chineseVoice.name); } } setupEventListeners() { // 语音识别事件 this.voiceRecognition.addEventListener('listeningStart', () => { this.updateVoiceUI('listening'); this.audioFeedback.startVisualization(document.getElementById('audioVisualizer')); }); this.voiceRecognition.addEventListener('interimResult', (data) => { this.updateTranscript(data.interimTranscript, data.finalTranscript); }); this.voiceRecognition.addEventListener('listeningEnd', (finalTranscript) => { this.updateVoiceUI('inactive'); this.audioFeedback.stopVisualization(); if (finalTranscript.trim()) { this.processUserInput(finalTranscript); } }); this
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/27 6:58:55

AI时代:UI设计师效率翻倍的秘密

博主介绍 &#x1f468;‍&#x1f4bb; 了解博主&#xff1a;波仔椿 &#x1f4d6; 人生箴言&#xff1a;AI 不会淘汰人&#xff0c;但会用 AI 的人会淘汰不会用的人。 &#x1f9f0; 我的专栏&#xff1a;AI杂谈会 文章内容 上周我帮一个做UI设计的朋友改项目方案&#xff…

作者头像 李华
网站建设 2026/7/27 6:54:17

基于TI F29H85x的UART FOTA实现:A/B分区与HSM安全升级详解

1. 项目概述&#xff1a;为什么FOTA是嵌入式开发的“必修课”&#xff1f;在嵌入式项目里&#xff0c;最让人头疼的场景之一莫过于设备已经部署到现场&#xff0c;却发现了一个必须修复的Bug&#xff0c;或者需要增加一个新功能。传统的做法是派人去现场&#xff0c;用JTAG或者…

作者头像 李华
网站建设 2026/7/27 6:51:33

实体门店AI裂变引流实战:小魔推碰一碰技术解析

1. 实体门店引流困境与破局之道作为一家经营了五年社区烘焙店的老板&#xff0c;我深知实体门店在引流获客上的无力感。每天清晨四点起床准备面包&#xff0c;晚上十点关门盘点&#xff0c;却依然要面对客流稀少的焦虑。传统的发传单、本地公众号投放效果越来越差&#xff0c;而…

作者头像 李华
网站建设 2026/7/27 6:51:03

风电功率超短期预测与并网调度关键技术解析

1. 风电功率预测与调度模型概述风电功率超短期预测与并网优化调度是当前新能源电力系统研究的核心课题。随着风电装机容量在全球能源结构中的占比不断提升&#xff0c;如何准确预测风电出力并实现高效并网调度&#xff0c;已成为电力系统运行的关键技术瓶颈。我从事风电预测算法…

作者头像 李华
网站建设 2026/7/27 6:50:21

储能 PCS 通讯协议与 BMS 交互匹配技术详解

引言 在储能系统中,储能变流器(Power Conversion System, PCS)与电池管理系统(Battery Management System, BMS)是两大核心部件。PCS负责交直流电能的转换与控制,BMS则负责电池状态的监测、评估与管理。两者之间的高效、可靠、实时的数据交互,是保障储能系统安全、稳定…

作者头像 李华