基于 shadcn/ui 的 ElevenLabs UI 组件库:快速构建 AI 语音应用前端
1. 项目概述为什么我们需要 ElevenLabs UI如果你正在用 React 和 Next.js 捣鼓 AI 语音应用或者想给产品加个能说会道的智能助手那你大概率绕不开两个东西一个是 ElevenLabs 强大的语音合成 API另一个是 shadcn/ui 这个灵活的前端组件库。但把它们俩揉在一起从零开始搭一个像样的界面体验过的人都知道那感觉就像用乐高积木拼一座城堡——创意无限但过程琐碎而且总有些通用零件比如音频播放器、语音波形、AI 助手头像你得反复造轮子。ElevenLabs UI 的出现就是为了解决这个痛点。它不是一个全新的 UI 框架而是基于 shadcn/ui 生态构建的一个专用组件注册表。你可以把它理解为一个“乐高官方扩展包”里面全是预先设计好、开箱即用、并且专为 AI 语音和智能体应用场景优化的 React 组件。比如那个标志性的、会随着语音脉动变化的“能量球”Orb或者一个集成了播放、暂停、进度条和波形显示的完整音频播放器这些组件在 ElevenLabs UI 里都已经帮你封装好了你只需要一条命令就能把它们“安装”到自己的项目中然后像使用普通 shadcn/ui 组件一样去定制和组合。这背后的核心价值是提效和一致性。提效在于你不用再花几天时间去研究如何用canvas画一个平滑的波形或者如何让一个球体的动画与音频流实时同步——这些复杂的前端交互逻辑ElevenLabs 的工程师已经帮你实现了。一致性在于所有组件都遵循 shadcn/ui 的设计哲学代码直接属于你的项目完全可定制没有黑盒依赖。这意味着你可以随意修改源码调整样式甚至基于它们二次开发打造出独一无二但又具备专业交互体验的 AI 应用界面。2. 核心组件深度解析与选型思路ElevenLabs UI 提供的组件主要围绕两个核心场景音频可视化和智能体交互。理解每个组件的设计意图和适用场景能帮助你在项目中做出更合适的选择。2.1 音频可视化组件不止是“能响”在 AI 语音应用中音频不仅仅是后台播放的媒体文件更是用户与智能体交互的核心媒介。因此相关的 UI 组件需要提供丰富的状态反馈和交互能力。Orb能量球/语音球这是 ElevenLabs 最具辨识度的视觉元素之一。它不仅仅是一个装饰性的动画而是一个实时的语音活动指示器。核心原理组件内部通常会通过 Web Audio API 或类似的库如wavesurfer.js分析正在播放的音频流获取实时的频率或振幅数据。然后这些数据被映射到球体的视觉属性上比如半径的脉动、颜色的渐变或内部“能量”的流动效果。使用场景语音合成播放当 ElevenLabs API 返回的语音流开始播放时Orb 随之激活、脉动给用户明确的“正在发声”反馈。语音输入状态在录音或语音识别场景Orb 可以表示“正在聆听”或“处理中”的状态。智能体“思考”状态当 AI 在处理用户请求、尚未开始说话时一个缓慢脉动或旋转的 Orb 可以直观地表示“正在思考”。选型考量如果你的应用强依赖于语音交互并且希望有一个现代、动感的品牌视觉锤Orb 几乎是必选组件。它极大地增强了应用的“活”感和科技感。Waveform波形图一个功能更专业的音频可视化组件。与 Orb 的抽象表达不同波形图提供的是对音频信号的直接、具象呈现。核心功能可视化显示整个音频文件的波形轮廓让用户对音频长度和强度分布有直观了解。交互支持点击波形任意位置进行跳播这是专业音频播放器的标配功能。区域高亮可以高亮显示当前播放进度甚至支持未来可能扩展的选择音频片段功能。使用场景音频编辑或预览当用户生成了多段语音需要选择或剪辑时。长音频播放对于播客、长对话等场景波形图提供了更好的进度控制。与 Orb 互补Orb 负责“氛围感”和状态指示Waveform 负责“精确控制”和信息展示两者可以结合使用。选型考量如果你的应用涉及用户对生成语音的精细控制如复听某一段、或需要展示音频的结构那么 Waveform 组件必不可少。Audio Player音频播放器这是一个集大成者的复合组件。它很可能内部集成了播放控制按钮播放/暂停、进度条、时间显示、音量控制并且与上述的 Waveform 或 Orb 进行联动。核心价值提供了一套开箱即用、风格统一、功能完整的音频播放解决方案。你不用自己去拼接按钮、绑定事件、管理播放状态这个组件已经处理了所有脏活累活并且确保了交互逻辑的一致性。选型考量对于绝大多数需要播放 ElevenLabs 生成语音的应用直接使用这个 Audio Player 组件是最快、最稳妥的选择可以避免自己实现时可能遇到的跨浏览器兼容性、移动端触摸事件处理等问题。2.2 智能体交互组件赋予 AI 人格化界面当 AI 不仅仅是后台接口而是一个具有“角色”的智能体时其 UI 也需要相应的进化。Voice Agent语音智能体界面这个组件可能是一个更复杂的“容器”或“场景”它定义了智能体与用户交互的完整界面框架。可能包含的元素智能体头像/标识如 Orb 或自定义头像。对话气泡显示智能体的文字回复。交互控件语音输入按钮、文本输入框、功能按钮如重新生成、复制文本。状态指示器连接状态、思考状态、说话状态。设计意图它提供了一套最佳实践告诉你如何将这些零散的组件Orb, 按钮输入框有机地组合在一起形成一个用户体验流畅的对话界面。这不仅仅是 UI 组件的拼装更是交互逻辑的封装。选型考量如果你正在构建一个端到端的语音对话应用例如客服助手、虚拟伴侣、交互式故事讲述者直接基于或参考这个 Voice Agent 组件进行开发可以节省大量的界面布局和交互设计时间。其他潜在组件根据官方文档的暗示可能还包括录音组件集成浏览器的MediaRecorderAPI提供美观的录音按钮和状态反馈。设置面板组件用于调整语音模型、音色、语速等 ElevenLabs API 参数样式与整体设计保持一致。注意组件选型的心得不要试图在第一个版本中就安装和使用所有组件。我的建议是先从最核心的Audio Player和Orb开始。前者解决基础功能后者提升产品气质。等主流程跑通后再根据实际需求引入 Waveform如果需要精细控制或 Voice Agent如果要构建完整对话流。这样能避免项目初期被过多的组件代码干扰更专注于核心业务逻辑。3. 从零开始完整集成与实操指南理论说再多不如动手搭一遍。下面我将以一个全新的 Next.js 15App Router项目为例带你完整走一遍集成 ElevenLabs UI 的流程并穿插我踩过的一些坑和最佳实践。3.1 环境准备与项目初始化首先确保你的开发环境符合要求。Node.js 18 是必须的我推荐使用nvm或fnm这类 Node 版本管理工具方便切换。# 1. 创建新的 Next.js 项目使用 TypeScript 和 Tailwind CSS 是强推荐 npx create-next-applatest my-ai-voice-app # 交互式命令行中请确保选择以下选项 # - TypeScript: Yes # - ESLint: Yes # - Tailwind CSS: Yes # - App Router: Yes (推荐) # - 其他选项按需选择 # 2. 进入项目目录 cd my-ai-voice-app # 3. 初始化 shadcn/ui。这是 ElevenLabs UI 的基石必须先做。 npx shadcnlatest init在执行shadcn/ui初始化时命令行会问你几个问题这里有几个关键选择样式选择new-york或default都可以ElevenLabs UI 组件会适配你的选择。我个人偏好new-york更现代。颜色按喜好选择。全局 CSS选择app/globals.css。组件目录默认是components/ui。记住这个路径ElevenLabs UI 的组件也会安装到这里。使用别名强烈建议选Yes。这会让你的 import 路径更简洁例如/components/ui/button。初始化完成后你的项目结构里会多出一个components/ui目录里面可能已经有一个button.tsx等基础组件。同时tailwind.config.ts和components.json文件也被正确配置。3.2 安装 ElevenLabs UI 组件现在主角登场。我们有多种方式安装组件但强烈推荐使用 ElevenLabs 官方的 CLI 工具因为它能智能处理依赖和初始化。方法一使用 ElevenLabs CLI推荐这是最省心的方法尤其适合新手或想快速安装所有组件的场景。# 安装所有组件一站式解决方案 npx elevenlabs/clilatest components add all执行这条命令后CLI 会做以下几件事你可以从终端输出中观察到检查环境确认你的项目是否已初始化 shadcn/ui。安装依赖自动将 ElevenLabs UI 组件所需的额外 npm 包如处理音频的库、动画库等添加到你的package.json。拉取组件代码将所有组件的源代码.tsx文件下载到你配置的组件目录如components/ui中。你会看到新增了orb.tsx、audio-player.tsx等文件。更新配置文件可能会更新components.json确保样式和主题能正确应用。方法二使用 shadcn/ui CLI 安装特定组件如果你只想先尝试一两个组件或者更喜欢手动控制可以用这种方法。# 安装 Orb 组件 npx shadcnlatest add https://ui.elevenlabs.io/r/orb.json # 安装 Audio Player 组件 npx shadcnlatest add https://ui.elevenlabs.io/r/audio-player.json这种方式更像传统的shadcn/ui添加组件直接通过组件的注册表 JSON 地址来安装。你可以在 ElevenLabs UI 组件文档 找到所有组件的 JSON 链接。实操心得网络问题与镜像源在运行上述npx命令时可能会因为网络原因导致下载缓慢或失败。一个有效的解决办法是切换 npm 镜像源到国内镜像如淘宝源。但更关键的是npx会从 GitHub 或其他地方下载组件源码如果遇到问题可以尝试设置命令行代理或使用更稳定的网络环境。如果add all失败可以退而求其次用方法二逐个安装你最需要的组件。3.3 在项目中实际使用组件假设我们已经成功安装了Orb和AudioPlayer组件。现在让我们在一个页面中实际使用它们。首先我们需要一个音频源。这里我们模拟一个从 ElevenLabs API 获取的语音音频 URL。步骤 1创建演示页面在app目录下创建一个新页面例如app/demo/page.tsx。// app/demo/page.tsx import { AudioPlayer } from /components/ui/audio-player; import { Orb } from /components/ui/orb; // 这是一个模拟的 ElevenLabs 生成的语音文件 URL // 在实际项目中这个 URL 应该来自你的后端 API 或 ElevenLabs API 的直接响应 const MOCK_AUDIO_URL https://example.com/path/to/your/elevenlabs-generated-speech.mp3; export default function DemoPage() { // 假设我们有一个状态来表示音频是否在播放 // 在实际中AudioPlayer 组件可能会内部管理这个状态 const isPlaying false; return ( div classNamecontainer mx-auto p-8 space-y-12 section h1 classNametext-3xl font-bold mb-6ElevenLabs UI 组件演示/h1 p classNametext-muted-foreground 以下展示了如何集成和使用 ElevenLabs 提供的专用 UI 组件。 /p /section section classNamespace-y-6 h2 classNametext-2xl font-semibold1. Orb - 语音活动指示器/h2 div classNameflex flex-col items-center justify-center p-8 border rounded-lg bg-gradient-to-br from-gray-50 to-white p classNamemb-4 text-sm text-center text-gray-600 下方的 Orb 会在音频播放时产生脉动动画。当前状态{isPlaying ? 播放中 : 静止} /p {/* 使用 Orb 组件。size 和 interactive 是它可能支持的属性 */} Orb sizelg // 可能是 sm, md, lg state{isPlaying ? speaking : idle} // 状态驱动动画 classNameshadow-lg / p classNamemt-4 text-xs text-gray-500 提示Orb 的视觉反馈能让用户直观感知 AI 的“活动”状态。 /p /div /section section classNamespace-y-6 h2 classNametext-2xl font-semibold2. AudioPlayer - 完整播放控件/h2 div classNamep-6 border rounded-lg {/* 使用 AudioPlayer 组件。 它可能需要一个 src 属性并内部处理播放逻辑。 实际属性名请参考安装后组件源码中的定义。 */} AudioPlayer src{MOCK_AUDIO_URL} title示例语音欢迎使用 ElevenLabs showWaveform{true} // 是否显示波形图 autoPlay{false} classNamew-full / p classNamemt-4 text-sm text-gray-600 这个播放器集成了进度控制、音量调节和波形可视化。尝试点击波形进行跳播。 /p /div /section section classNametext-sm text-gray-500 border-t pt-6 p strong注意/strong 这是一个静态演示。要使其完全交互你需要将组件与真实的音频流状态例如使用 useState 和 useRef 管理播放以及 ElevenLabs API 的响应进行连接。 /p /section /div ); }步骤 2处理真实的音频流上面的例子使用了模拟的静态音频 URL。在实际的 ElevenLabs 集成中你通常是通过 API 获取一个音频流如audio/mpeg格式。这时你需要使用 HTML5 的audio元素或Howler.js等库来播放并将播放状态与 Orb 等组件同步。一个更接近实战的简化示例框架// 这是一个更高级的示例展示状态管理思路 use client; // 因为要用到状态和效果必须是客户端组件 import { useState, useRef } from react; import { Orb } from /components/ui/orb; // 假设 AudioPlayer 是一个受控组件 import { AudioPlayer } from /components/ui/audio-player; export function RealVoiceDemo() { const [isPlaying, setIsPlaying] useState(false); const [audioUrl, setAudioUrl] useStatestring | null(null); const audioRef useRefHTMLAudioElement(null); // 模拟调用 ElevenLabs API 生成语音并获取 URL const generateAndPlayVoice async (text: string) { // 1. 调用你的后端或直接调用 ElevenLabs API // const response await fetch(/api/generate-voice, { method: POST, body: ... }); // const data await response.json(); // const url data.audioUrl; // 2. 这里用模拟数据 const mockUrl https://api.elevenlabs.io/v1/...; // 真实的 API 端点 setAudioUrl(mockUrl); setIsPlaying(true); // 3. 在实际中你可能需要直接控制 audio 元素或使用 AudioPlayer 组件的方法 if (audioRef.current) { audioRef.current.src mockUrl; audioRef.current.play().then(() { // 播放开始 }).catch(e console.error(播放失败:, e)); } }; const handlePlayPause () { if (!audioRef.current) return; if (isPlaying) { audioRef.current.pause(); } else { audioRef.current.play(); } setIsPlaying(!isPlaying); }; return ( div Orb state{isPlaying ? speaking : idle} / button onClick{() generateAndPlayVoice(你好世界)} 生成并播放语音 /button button onClick{handlePlayPause} {isPlaying ? 暂停 : 播放} /button {/* 一个隐藏的 audio 元素用于实际播放控制 */} audio ref{audioRef} onEnded{() setIsPlaying(false)} onPause{() setIsPlaying(false)} onPlay{() setIsPlaying(true)} classNamehidden / {/* 或者使用受控的 AudioPlayer 组件 */} {audioUrl ( AudioPlayer src{audioUrl} isPlaying{isPlaying} onPlayPause{handlePlayPause} // ... 其他属性 / )} /div ); }核心技巧状态同步是关键在实际集成中最需要精细处理的就是音频播放状态与UI 组件状态的同步。audio元素的onPlay、onPause、onEnded、onTimeUpdate等事件是你的好朋友。建议使用 React 状态管理库如 Zustand或 Context 来集中管理全局的音频播放状态这样 Orb、AudioPlayer 以及其他需要感知音频状态的组件都能轻松访问和响应。4. 样式定制与主题适配ElevenLabs UI 基于 shadcn/ui因此继承了其强大的样式定制能力。所有组件都使用 CSS Variables 和 Tailwind CSS你可以轻松地让它们融入你的品牌设计。4.1 修改组件样式由于组件的源代码就在你的components/ui目录下直接修改它们是最直接的方式。例如打开orb.tsx你可能会找到控制颜色和动画的 CSS 变量或 Tailwind 类名。// 假设 Orb 组件内部有类似这样的结构 function Orb({ state, size, className }) { return ( div className{cn( relative rounded-full bg-gradient-to-br from-primary/20 to-primary/5, // 默认渐变 animate-pulse-slow, // 默认动画 state speaking animate-pulse-fast bg-gradient-to-br from-primary to-primary/60, className // 允许从外部传入的类名这是关键 )} style{{ width: sizeMap[size], height: sizeMap[size] }} / ); }你可以通过传入className属性来覆盖默认样式Orb state{state} sizemd classNamebg-gradient-to-br from-purple-500/30 to-pink-500/20 shadow-2xl /4.2 全局主题定制更系统的做法是修改项目的全局 CSS 变量。在app/globals.css中shadcn/ui 已经定义了一套基于:root的变量。/* app/globals.css */ tailwind base; tailwind components; tailwind utilities; layer base { :root { --background: 0 0% 100%; --foreground: 222.2 84% 4.9%; --primary: 221.2 83.2% 53.3%; /* 默认的主蓝色 */ --primary-foreground: 210 40% 98%; /* ... 其他变量 */ } .dark { --background: 222.2 84% 4.9%; --foreground: 210 40% 98%; --primary: 217.2 91.2% 59.8%; /* ... */ } }如果你想改变 Orb 等组件使用的主题色只需修改--primary对应的 HSL 值即可。ElevenLabs UI 组件会自动使用这些 CSS 变量。4.3 处理动态主题与暗黑模式如果你的应用支持暗黑模式确保在tailwind.config.ts中正确配置了darkMode选项通常是class策略。shadcn/ui 和 ElevenLabs UI 组件都会自动响应dark类名。// 在布局或根组件中提供主题切换逻辑 use client; import { ThemeProvider } from next-themes; // 一个流行的主题管理库 export function Providers({ children }) { return ( ThemeProvider attributeclass defaultThemesystem enableSystem {children} /ThemeProvider ); }然后在app/layout.tsx中用Providers包裹内容。这样当html标签上有classdark时所有组件的暗黑样式都会生效。5. 常见问题排查与性能优化在实际使用中你可能会遇到一些问题。以下是一些常见情况的排查思路和优化建议。5.1 安装与构建问题问题现象可能原因解决方案npx elevenlabs/cli add all失败提示 shadcn/ui 未初始化CLI 检测不到有效的 shadcn/ui 配置。1. 确保在项目根目录运行npx shadcnlatest init并成功完成。2. 检查项目根目录下是否存在components.json文件。组件安装后页面报错Cannot find module /components/ui/orb路径别名/*未正确配置。1. 检查tsconfig.json中的paths配置/*: [./*]。2. 重启你的开发服务器npm run dev。3. 对于某些编辑器如 VSCode可能需要重启语言服务。组件样式不生效看起来“很丑”Tailwind CSS 未正确编译或组件 CSS 变量未加载。1. 确保app/globals.css正确导入了tailwind指令。2. 运行npm run build检查是否有 CSS 相关的构建错误。3. 检查浏览器开发者工具看组件的 CSS 类名和变量是否被正确应用。5.2 运行时与交互问题问题现象可能原因解决方案Orb 动画不流畅有卡顿动画可能使用了高性能消耗的属性如box-shadow的动画或者在低性能设备上运行。1. 检查是否在大量组件或复杂页面中使用多个 Orb。考虑减少同时活动的 Orb 数量。2. 尝试使用 CSSwill-change: transform;或transform: translateZ(0);来提示浏览器进行 GPU 加速需谨慎测试。3. 确保音频分析逻辑如果有时不在主线程造成阻塞。AudioPlayer 在移动端无法播放移动端浏览器特别是 iOS Safari对音频自动播放和程序化播放有严格限制。1.永远不要设置autoPlay除非在用户手势事件触发后。2. 音频播放必须在用户手势事件如onClick的回调函数中触发。3. 使用audioElement.play().catch(e {})捕获错误并提示用户“点击以播放音频”。波形图Waveform不显示或无法点击跳播音频 URL 可能跨域或者音频格式不被波形库支持。1. 确保音频资源支持 CORS跨域资源共享。如果音频来自 ElevenLabs CDN通常是支持的。2. 检查音频 URL 是否有效且可访问。3. 查看浏览器控制台是否有关于音频解码或 Canvas 绘制的错误信息。5.3 性能优化建议按需加载音频不要在页面初始化时就加载所有语音音频。使用useState或useSWR在用户需要时例如点击“播放”按钮再获取音频 URL 或 Blob。懒加载组件如果 ElevenLabs UI 组件特别是包含复杂 Canvas 绘制的 Waveform不在首屏显示可以使用next/dynamic进行动态导入。import dynamic from next/dynamic; const HeavyAudioPlayer dynamic(() import(/components/ui/audio-player), { ssr: false });管理音频实例避免在组件中创建多个隐藏的audio元素实例。考虑使用一个全局的音频上下文或状态管理器来共享单个音频实例。清理资源在组件卸载时确保清理音频分析器如AnalyserNode和事件监听器防止内存泄漏。6. 进阶构建一个完整的语音助手前端掌握了单个组件的使用后我们可以尝试将它们组合起来构建一个迷你版的语音助手前端界面。这个例子将串联起语音生成、播放、状态反馈的完整闭环。// app/assistant/page.tsx - 一个简化的语音助手界面 use client; import { useState, useRef, useEffect } from react; import { Orb } from /components/ui/orb; import { AudioPlayer } from /components/ui/audio-player; import { Button } from /components/ui/button; // shadcn/ui 的基础按钮 import { Textarea } from /components/ui/textarea; // shadcn/ui 的文本输入框 import { Loader2, Send } from lucide-react; // 图标库 type AssistantState idle | thinking | speaking; export default function AssistantPage() { const [inputText, setInputText] useState(); const [conversation, setConversation] useStateArray{role: user | assistant, text: string}([]); const [assistantState, setAssistantState] useStateAssistantState(idle); const [currentAudioUrl, setCurrentAudioUrl] useStatestring | null(null); const [isLoading, setIsLoading] useState(false); // 模拟调用 AI 后端生成回复和语音 const handleSendMessage async () { if (!inputText.trim()) return; const userMessage inputText; setInputText(); setConversation(prev [...prev, { role: user, text: userMessage }]); setIsLoading(true); setAssistantState(thinking); try { // 1. 模拟网络请求延迟 await new Promise(resolve setTimeout(resolve, 1000)); // 2. 模拟 AI 回复实际中这里调用你的 LLM API const aiResponse 这是对“${userMessage}”的模拟回复。在实际中这里应接入 GPT、Claude 或你的 Agent 服务。; // 3. 模拟调用 ElevenLabs TTS API实际中调用你的后端或直接调用 ElevenLabs // const audioBlob await generateSpeech(aiResponse); // const audioUrl URL.createObjectURL(audioBlob); const mockAudioUrl /api/placeholder-audio.mp3; // 一个占位符音频 // 4. 更新状态 setConversation(prev [...prev, { role: assistant, text: aiResponse }]); setCurrentAudioUrl(mockAudioUrl); setAssistantState(speaking); // 注意实际播放应由 AudioPlayer 组件或 audio 元素控制这里假设 AudioPlayer 会自动播放 src } catch (error) { console.error(处理消息失败:, error); setConversation(prev [...prev, { role: assistant, text: 抱歉我出错了。 }]); } finally { setIsLoading(false); // 语音播放结束后状态应切回 idle这需要监听 audio 的 onEnded 事件 } }; const handleAudioEnded () { setAssistantState(idle); }; return ( div classNamemin-h-screen bg-gradient-to-b from-background to-muted/20 p-4 md:p-8 div classNamemax-w-4xl mx-auto {/* 头部 */} header classNametext-center mb-10 h1 classNametext-4xl font-bold tracking-tightAI 语音助手/h1 p classNametext-muted-foreground mt-2与您的智能助手进行对话/p /header div classNamegrid grid-cols-1 lg:grid-cols-3 gap-8 {/* 左侧助手状态与 Orb */} div classNamelg:col-span-1 flex flex-col items-center justify-start space-y-8 div classNamerelative Orb sizexl state{assistantState speaking ? speaking : assistantState thinking ? listening : idle} classNameshadow-2xl / div classNameabsolute -bottom-6 left-1/2 transform -translate-x-1/2 bg-primary text-primary-foreground px-3 py-1 rounded-full text-sm font-medium whitespace-nowrap {assistantState idle 等待中} {assistantState thinking 思考中...} {assistantState speaking 说话中} /div /div div classNametext-center space-y-2 h3 classNamefont-semibold状态说明/h3 ul classNametext-sm text-muted-foreground space-y-1 li• span classNametext-primary脉动/span正在播放语音/li li• span classNametext-yellow-500缓慢旋转/span正在处理您的请求/li li• span classNametext-gray-400静止/span准备就绪/li /ul /div /div {/* 右侧对话区域与控制区 */} div classNamelg:col-span-2 space-y-8 {/* 对话历史 */} div classNameborder rounded-xl bg-card p-6 h-[400px] overflow-y-auto {conversation.length 0 ? ( div classNameh-full flex items-center justify-center text-muted-foreground 对话将在这里显示... /div ) : ( div classNamespace-y-4 {conversation.map((msg, idx) ( div key{idx} className{flex ${msg.role user ? justify-end : justify-start}} div className{max-w-[80%] rounded-2xl px-4 py-3 ${msg.role user ? bg-primary text-primary-foreground rounded-br-none : bg-muted border rounded-bl-none }} {msg.text} /div /div ))} {isLoading ( div classNameflex justify-start div classNamebg-muted border rounded-2xl rounded-bl-none px-4 py-3 flex items-center gap-2 Loader2 classNameh-4 w-4 animate-spin / span助手正在思考.../span /div /div )} /div )} /div {/* 当前播放器 */} {currentAudioUrl ( div classNameborder rounded-xl p-4 p classNametext-sm font-medium mb-2最新回复语音/p AudioPlayer src{currentAudioUrl} onEnded{handleAudioEnded} autoPlay{true} showWaveform{true} / /div )} {/* 输入区域 */} div classNameborder rounded-xl bg-card p-4 space-y-4 Textarea placeholder输入您想对助手说的话... value{inputText} onChange{(e) setInputText(e.target.value)} onKeyDown{(e) { if (e.key Enter !e.shiftKey) { e.preventDefault(); handleSendMessage(); } }} classNamemin-h-[100px] resize-none disabled{isLoading || assistantState speaking} / div classNameflex justify-between items-center div classNametext-xs text-muted-foreground 按 Enter 发送ShiftEnter 换行 /div Button onClick{handleSendMessage} disabled{isLoading || !inputText.trim() || assistantState speaking} sizelg {isLoading ? ( Loader2 classNamemr-2 h-4 w-4 animate-spin / 处理中 / ) : ( Send classNamemr-2 h-4 w-4 / 发送 / )} /Button /div /div /div /div /div /div ); }这个示例虽然简化了后端集成但它展示了一个完整的前端交互闭环用户输入 - 状态指示Orb- 模拟 AI 处理 - 显示文本回复 - 播放语音AudioPlayer- 状态重置。你可以在此基础上替换模拟部分为真实的 ElevenLabs TTS API 调用和你的大语言模型 API 调用快速构建出功能丰富的原型甚至生产级应用。ElevenLabs UI 的价值在于它提供了这些交互中最耗时、最需要专业前端知识的 UI 部分让你能专注于核心的 AI 逻辑和业务集成。从 Orb 的动画到 AudioPlayer 的完整控件这些经过打磨的组件能显著提升你产品的专业度和开发效率。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2555674.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!