使用 OpenAI GPT-4o-mini 和文本转语音创建语音助手界面
中级
这是一个Support Chatbot, AI Chatbot领域的自动化工作流,包含 14 个节点。主要使用 Html, Webhook, Agent, OpenAi, RespondToWebhook 等节点。 使用 OpenAI GPT-4o-mini 和文本转语音创建语音助手界面
前置要求
- •HTTP Webhook 端点(n8n 会自动生成)
- •OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"meta": {
"instanceId": "6052a1b29f061469e8139dae44556603650099c3365d7598798f132ae827fa1c"
},
"nodes": [
{
"id": "251e4d25-f04b-4861-b4fb-c9aa63654d2e",
"name": "语音接口端点",
"type": "n8n-nodes-base.webhook",
"position": [
880,
180
],
"webhookId": "71ac230d-5949-41ba-b05e-761cb5cb07f3",
"parameters": {
"path": "voice-assistant",
"options": {},
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "299de4f0-2bdd-46da-bfdb-35128a6240e0",
"name": "语音助手界面",
"type": "n8n-nodes-base.html",
"position": [
1100,
180
],
"parameters": {
"html": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <title>AI Voice Assistant</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <style>\n body {\n background-color: #000;\n color: white;\n font-family: 'Segoe UI', sans-serif;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n overflow: hidden;\n }\n\n .orb-container {\n position: relative;\n }\n\n .orb {\n width: 200px;\n height: 200px;\n background: radial-gradient(circle at 30% 30%, #00ffff, #004d4d);\n border-radius: 50%;\n box-shadow: 0 0 40px #00ffff88;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 2; /* Ensures clickability */\n }\n\n .ring {\n position: absolute;\n top: -20px;\n left: -20px;\n width: 240px;\n height: 240px;\n border-radius: 50%;\n box-shadow: 0 0 30px #00ffff55;\n animation: pulse 2s infinite;\n z-index: 1;\n pointer-events: none; /* Prevents click interference */\n }\n \n .orb.listening {\n background: radial-gradient(circle at 30% 30%, #00ffcc, #005c5c);\n box-shadow: 0 0 50px #00ffff;\n }\n\n .orb.playing {\n background: radial-gradient(circle at 30% 30%, #ff00ff, #520052);\n box-shadow: 0 0 50px #ff00ff99;\n }\n\n .ring.listening {\n animation: vibrate 0.4s infinite;\n }\n\n .ring.playing {\n animation: glow 1s ease-in-out infinite alternate;\n }\n\n @keyframes pulse {\n 0%, 100% { transform: scale(1); opacity: 0.6; }\n 50% { transform: scale(1.2); opacity: 1; }\n }\n\n @keyframes vibrate {\n 0% { transform: scale(1.05); }\n 50% { transform: scale(1.15); }\n 100% { transform: scale(1.05); }\n }\n\n @keyframes glow {\n 0% { box-shadow: 0 0 40px #ff00ff88; }\n 100% { box-shadow: 0 0 60px #ff00ffcc; }\n }\n\n .status-text {\n margin-top: 20px;\n font-size: 18px;\n color: #aaa;\n font-weight: 300;\n font-style: italic;\n }\n </style>\n</head>\n<body>\n <div class=\"orb-container\">\n <div id=\"ring\" class=\"ring\"></div>\n <div id=\"orb\" class=\"orb\" title=\"Click to speak with AI\"></div>\n </div>\n <div id=\"status\" class=\"status-text\">Click to speak</div>\n\n <audio id=\"beep\" src=\"https://www.soundjay.com/button/sounds/button-3.mp3\" preload=\"auto\"></audio>\n\n <script>\n const orb = document.getElementById('orb');\n const ring = document.getElementById('ring');\n const statusText = document.getElementById('status');\n const beep = document.getElementById('beep');\n\n let recognition;\n let lastTranscript = \"\";\n let silenceTimeout;\n\n // Initialize speech recognition\n function startRecognition() {\n if (!('webkitSpeechRecognition' in window)) {\n alert('This browser does not support speech recognition.');\n return;\n }\n\n beep.play();\n recognition = new webkitSpeechRecognition();\n recognition.lang = 'en-US'; // Change to your preferred language\n recognition.interimResults = true;\n recognition.continuous = true;\n lastTranscript = \"\";\n\n recognition.onstart = () => {\n orb.classList.add('listening');\n ring.classList.add('listening');\n statusText.textContent = \"Listening...\";\n };\n\n recognition.onresult = (event) => {\n for (let i = event.resultIndex; i < event.results.length; ++i) {\n if (event.results[i].isFinal) {\n lastTranscript += event.results[i][0].transcript;\n }\n }\n\n // Reset silence timeout\n clearTimeout(silenceTimeout);\n silenceTimeout = setTimeout(stopRecognition, 1000);\n };\n\n recognition.onerror = (event) => {\n console.error('Error:', event.error);\n orb.classList.remove('listening');\n ring.classList.remove('listening');\n statusText.textContent = \"Error: \" + event.error;\n };\n\n recognition.onend = () => {\n orb.classList.remove('listening');\n ring.classList.remove('listening');\n };\n\n recognition.start();\n }\n\n // Stop recognition and send to webhook\n async function stopRecognition() {\n if (recognition) {\n recognition.stop();\n orb.classList.remove('listening');\n ring.classList.remove('listening');\n statusText.textContent = \"Processing...\";\n\n if (lastTranscript.trim() !== '') {\n try {\n // IMPORTANT: Replace YOUR_WEBHOOK_URL_HERE with the actual webhook URL from the 'Audio Processing Endpoint' node\n const response = await fetch(\"YOUR_WEBHOOK_URL_HERE\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ question: lastTranscript.trim() })\n });\n\n if (!response.ok) throw new Error(\"Server response error\");\n\n const blob = await response.blob();\n const audioURL = URL.createObjectURL(blob);\n const audio = new Audio(audioURL);\n\n audio.onplay = () => {\n orb.classList.add('playing');\n ring.classList.add('playing');\n statusText.textContent = \"Responding...\";\n };\n\n audio.onended = () => {\n orb.classList.remove('playing');\n ring.classList.remove('playing');\n statusText.textContent = \"Click to speak\";\n };\n\n audio.play();\n\n } catch (err) {\n console.error(\"Error sending or processing response:\", err);\n statusText.textContent = \"Error communicating with AI\";\n }\n }\n }\n }\n\n // Click handler for the orb\n orb.addEventListener('click', () => {\n if (recognition && recognition.running) {\n stopRecognition();\n } else {\n startRecognition();\n }\n });\n </script>\n</body>\n</html>\n"
},
"typeVersion": 1.2
},
{
"id": "cbfca6b1-5b62-414d-a71b-e5a6b03236f1",
"name": "发送 HTML 界面",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1300,
180
],
"parameters": {
"options": {},
"respondWith": "text",
"responseBody": "={{ $json.html }}"
},
"typeVersion": 1.1
},
{
"id": "028000ca-2232-4168-867b-88f53eab9760",
"name": "音频处理端点",
"type": "n8n-nodes-base.webhook",
"position": [
720,
720
],
"webhookId": "287d40b1-4172-4ba0-9a1d-6d971dd9cf68",
"parameters": {
"path": "process-audio",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "d86e58ed-a0be-4853-a1dd-7d59bd6d2c1f",
"name": "处理用户查询",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
940,
720
],
"parameters": {
"text": "={{ $json.body.question }}",
"options": {
"systemMessage": "You are a helpful AI assistant. Respond in a friendly and conversational manner."
},
"promptType": "define"
},
"typeVersion": 1.8
},
{
"id": "9f336bfd-1dfc-4d4a-9fad-74d3df57bf0c",
"name": "对话记忆",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
1040,
920
],
"parameters": {
"sessionKey": "voice-assistant-session",
"sessionIdType": "customKey",
"contextWindowLength": 30
},
"typeVersion": 1.3
},
{
"id": "4e400995-440d-4a2b-927c-9e612a649fe8",
"name": "发送音频响应",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1520,
720
],
"parameters": {
"options": {},
"respondWith": "binary"
},
"typeVersion": 1.1
},
{
"id": "e468576e-22b6-44ef-9b0e-d2a95d72d2aa",
"name": "生成语音响应",
"type": "@n8n/n8n-nodes-langchain.openAi",
"disabled": true,
"position": [
1300,
720
],
"parameters": {
"input": "={{ $json.output }}",
"voice": "onyx",
"options": {},
"resource": "audio"
},
"typeVersion": 1.8
},
{
"id": "be60d217-d893-497f-87ff-a882ef11afc9",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
740,
-20
],
"parameters": {
"color": 5,
"width": 840,
"height": 420,
"content": "## 语音助手界面"
},
"typeVersion": 1
},
{
"id": "12cca86e-0868-4569-b89c-7f0d638254d1",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
620,
500
],
"parameters": {
"color": 3,
"width": 1100,
"height": 580,
"content": "## 后端处理"
},
"typeVersion": 1
},
{
"id": "e5a3196b-2865-4a62-b2d9-d755a67fcb38",
"name": "模板描述",
"type": "n8n-nodes-base.stickyNote",
"position": [
-120,
-20
],
"parameters": {
"color": 6,
"width": 600,
"height": 1460,
"content": "## 使用 n8n 和 OpenAI 的语音助手界面"
},
"typeVersion": 1
},
{
"id": "eba88594-9e7e-47b1-b1de-5e19e4607035",
"name": "设置说明",
"type": "n8n-nodes-base.stickyNote",
"position": [
1820,
-40
],
"parameters": {
"color": 7,
"width": 400,
"height": 500,
"content": "## ⚙️ 设置说明"
},
"typeVersion": 1
},
{
"id": "8eb03b82-cc02-46d9-b9b6-873718202e32",
"name": "自定义选项",
"type": "n8n-nodes-base.stickyNote",
"position": [
1820,
560
],
"parameters": {
"color": 7,
"width": 400,
"height": 440,
"content": "## 🎨 自定义选项"
},
"typeVersion": 1
},
{
"id": "c7d2aac4-5cb2-405c-8a4f-0f1020d76eec",
"name": "GPT-4o-mini 模型",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"disabled": true,
"position": [
900,
920
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "gpt-4o-mini"
},
"options": {}
},
"typeVersion": 1.2
}
],
"pinData": {},
"connections": {
"GPT-4o-mini Model": {
"ai_languageModel": [
[
{
"node": "Process User Query",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Process User Query": {
"main": [
[
{
"node": "Generate Voice Response",
"type": "main",
"index": 0
}
]
]
},
"Voice Assistant UI": {
"main": [
[
{
"node": "Send HTML Interface",
"type": "main",
"index": 0
}
]
]
},
"Conversation Memory": {
"ai_memory": [
[
{
"node": "Process User Query",
"type": "ai_memory",
"index": 0
}
]
]
},
"Generate Voice Response": {
"main": [
[
{
"node": "Send Audio Response",
"type": "main",
"index": 0
}
]
]
},
"Voice Interface Endpoint": {
"main": [
[
{
"node": "Voice Assistant UI",
"type": "main",
"index": 0
}
]
]
},
"Audio Processing Endpoint": {
"main": [
[
{
"node": "Process User Query",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
中级 - 客服机器人, AI 聊天机器人
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
AI驱动的Facebook页面支持聊天机器人:自动回复与智能客户处理
使用GPT-4.1的Facebook Messenger聊天机器人,支持人工升级
If
Set
Wait
+11
32 节点SpaGreen Creative
客服机器人
具备多步骤工具执行的AI驱动HVAC排程代理
通过AI代理、Google日历和Gmail自动化HVAC服务排程
Wait
Gmail
Webhook
+11
30 节点Bhuvanesh R
客服机器人
AI 智能体 - 短链接生成器
使用 GPT-4.1 和数据存储生成并管理短链接
Set
Code
Html
+10
18 节点Nghia Nguyen
杂项
使用WhatsApp AI助手和Google文档及Gemini自动处理客户支持
使用WhatsApp AI助手和Google文档及Gemini自动处理客户支持
If
Code
Webhook
+9
14 节点Jamot
客服机器人
The Recap AI - 牙科语音助手
使用 Gemini AI、Google Calendar 和 Sheets 自动化牙科预约
Webhook
Agent
Google Sheets Tool
+6
11 节点Lucas Walter
客服机器人
我的工作流4
具有专业助手的 GPT-4 多智能体聊天的精美 Web 界面
Code
Switch
Webhook
+4
24 节点Hugo
客服机器人