当前位置: 首页 > article >正文

基于 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 的完整控件这些经过打磨的组件能显著提升你产品的专业度和开发效率。

相关文章:

基于 shadcn/ui 的 ElevenLabs UI 组件库:快速构建 AI 语音应用前端

1. 项目概述:为什么我们需要 ElevenLabs UI? 如果你正在用 React 和 Next.js 捣鼓 AI 语音应用,或者想给产品加个能说会道的智能助手,那你大概率绕不开两个东西:一个是 ElevenLabs 强大的语音合成 API,另一…...

3步解锁Figma中文界面:告别语言障碍,专注创意设计

3步解锁Figma中文界面:告别语言障碍,专注创意设计 【免费下载链接】figmaCN 中文 Figma 插件,设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 还在为Figma的英文界面而头疼吗?每次设计时都要在专…...

OmniParser:纯视觉GUI智能体的屏幕解析与自动化操作实践

1. 项目概述:从屏幕截图到结构化元素的桥梁 在构建一个能真正“看懂”并操作图形用户界面的智能体时,最大的挑战是什么?不是让它理解复杂的自然语言指令,而是让它能像人类一样,一眼看懂屏幕上密密麻麻的图标、按钮、文…...

八大网盘直链下载助手:终极免费提速解决方案完整指南

八大网盘直链下载助手:终极免费提速解决方案完整指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云…...

避开网络配置大坑:有线桥接模式下,手把手在CentOS 7部署RuoYi前后端分离项目

避开网络配置大坑:有线桥接模式下,手把手在CentOS 7部署RuoYi前后端分离项目 在虚拟机环境中部署企业级开源项目时,网络配置往往是第一个拦路虎。我曾亲眼见过不少开发者在RuoYi项目部署初期,因为宿主机与虚拟机之间的网络连通问题…...

LingBot-Depth在摄影后期的神奇应用:一键生成景深,照片秒变大片

LingBot-Depth在摄影后期的神奇应用:一键生成景深,照片秒变大片 1. 摄影后期的新革命:从手动到智能 在摄影创作中,景深控制是塑造视觉焦点、营造氛围的关键技术。传统上,这需要摄影师在拍摄时就精确设置光圈和对焦距…...

如何安全高效备份QQ空间历史说说:GetQzonehistory完整解决方案

如何安全高效备份QQ空间历史说说:GetQzonehistory完整解决方案 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 在数字时代,我们的记忆越来越多地存储在云端社交平…...

SpringBoot 2.5.6 项目里,Swagger3 和 Knife4j 到底怎么配才不踩坑?

SpringBoot 2.5.6项目集成Swagger3与Knife4j的终极避坑指南 最近在技术社区看到不少开发者抱怨SpringBoot 2.5.x版本集成Swagger3时遇到的各种"玄学"问题。作为一个经历过多次版本兼容性折磨的老兵,我决定把这两年踩过的坑和解决方案整理成这份终极指南。…...

VLC播放器个性化皮肤终极指南:如何用VeLoCity主题打造完美播放体验

VLC播放器个性化皮肤终极指南:如何用VeLoCity主题打造完美播放体验 【免费下载链接】VeLoCity-Skin-for-VLC Castom skin for VLC Player 项目地址: https://gitcode.com/gh_mirrors/ve/VeLoCity-Skin-for-VLC 还在为VLC播放器单调的默认界面感到厌倦吗&…...

WaveTools鸣潮工具箱:终极游戏性能优化与抽卡分析完整指南

WaveTools鸣潮工具箱:终极游戏性能优化与抽卡分析完整指南 【免费下载链接】WaveTools 🧰鸣潮工具箱 项目地址: https://gitcode.com/gh_mirrors/wa/WaveTools 你是否正在《鸣潮》游戏中挣扎于复杂的画质设置?是否为多账号切换的繁琐操…...

ViGEmBus终极指南:免费解决Windows游戏手柄兼容性问题

ViGEmBus终极指南:免费解决Windows游戏手柄兼容性问题 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 你是否曾经遇到过这样的烦恼:心…...

大麦网Python自动抢票脚本终极指南:90%成功率的一键抢票方案

大麦网Python自动抢票脚本终极指南:90%成功率的一键抢票方案 【免费下载链接】Automatic_ticket_purchase 大麦网抢票脚本 项目地址: https://gitcode.com/GitHub_Trending/au/Automatic_ticket_purchase 在热门演唱会门票一票难求的时代,手动刷新…...

从VGG到ResNet:为什么现代CNN架构越来越‘嫌弃’池化层了?

从VGG到ResNet:池化层在现代CNN架构中的兴衰史 记得2014年第一次用VGG16完成图像分类任务时,模型里那些整齐的max pooling层就像高速公路上的收费站,每隔几个卷积层就必然出现。但当我去年复现ResNet-50时,突然发现这些曾经的&quo…...

Qwen3.5-4B-Claude-Opus Web镜像教程:跨域配置与前端集成方案

Qwen3.5-4B-Claude-Opus Web镜像教程:跨域配置与前端集成方案 1. 模型与镜像概述 Qwen3.5-4B-Claude-4.6-Opus-Reasoning-Distilled-GGUF 是基于 Qwen3.5-4B 的推理蒸馏模型,特别强化了结构化分析、分步骤回答以及代码与逻辑类问题的处理能力。该版本以…...

MinerU 2.5-1.2B新手入门:从零部署到成功提取PDF,保姆级全流程

MinerU 2.5-1.2B新手入门:从零部署到成功提取PDF,保姆级全流程 1. 引言:为什么选择MinerU处理PDF? PDF文档因其跨平台稳定性成为学术论文、技术文档和商业报告的主流格式。然而,当我们需要提取其中的内容时&#xff…...

如何通过3个核心步骤彻底解决动漫游戏配置难题?YuukiPS启动器深度解析

如何通过3个核心步骤彻底解决动漫游戏配置难题?YuukiPS启动器深度解析 【免费下载链接】Launcher-PC 项目地址: https://gitcode.com/gh_mirrors/la/Launcher-PC 你是否曾经为了启动一款动漫游戏而花费数小时配置环境?是否因为繁琐的补丁更新、账…...

深入解析MTKClient:联发科设备逆向工程与刷机工具的技术架构与应用实践

深入解析MTKClient:联发科设备逆向工程与刷机工具的技术架构与应用实践 【免费下载链接】mtkclient MTK reverse engineering and flash tool 项目地址: https://gitcode.com/gh_mirrors/mt/mtkclient MTKClient是一款专业的联发科芯片逆向工程与刷机工具&am…...

终极Fedora启动盘制作指南:Media Writer完全教程

终极Fedora启动盘制作指南:Media Writer完全教程 【免费下载链接】MediaWriter Fedora Media Writer - Write Fedora Images to Portable Media 项目地址: https://gitcode.com/gh_mirrors/me/MediaWriter Fedora Media Writer是制作Fedora启动盘的最佳工具&…...

WebGL加速方案解析!Anything to RealCharacters如何实现图片流式传输与渐进渲染

WebGL加速方案解析!Anything to RealCharacters如何实现图片流式传输与渐进渲染 1. 传统图片渲染的瓶颈与挑战 当使用Anything to RealCharacters引擎将2.5D图像转换为写实真人照片时,用户最常遇到的痛点就是生成后的预览等待时间。虽然我们的引擎基于…...

LangGraph智能体开发实战:从状态管理到生产部署全解析

1. 从零到一:构建你的第一个LangGraph智能体应用 如果你和我一样,在AI应用开发这条路上摸爬滚打了好几年,从早期的简单提示工程到复杂的多智能体系统,你一定会发现一个痛点: 如何将想法快速、可靠地转化为可运行的、…...

多智能体协作框架:用LLM构建自动化团队解决复杂任务

1. 项目概述:当LLM学会“开会”,一个多智能体协作框架的诞生如果你和我一样,在尝试用大语言模型(LLM)解决稍微复杂一点的任务时,总会遇到一个瓶颈:单个模型的能力边界。让它写个邮件、总结个文档…...

如何优化SQL长事务中的删除操作_拆分为小事务批量处理

长事务删除会卡死数据库,因其长期持有大量行锁、可能全表加锁,并导致binlog/redo log膨胀;应按主键分批删除,每批独立事务COMMIT,避免LIMIT循环和非安全WHERE条件。为什么长事务删除会卡死数据库长事务删除本质是把大量…...

TrueNAS Scale移植ARM平台:企业级存储的能效革新

1. TrueNAS Scale 移植到 ARM 平台的背景与意义TrueNAS 作为企业级存储解决方案的代表,长期以来仅支持 x86-64 架构。这个限制在 2023 年被社区开发者 Joel0 打破,他成功将 TrueNAS Scale 移植到了 64 位 ARM 平台。这个非官方移植版本的出现&#xff0c…...

CISSP工作经验不够5年怎么办?助理级(Associate)申请、维持与转正全流程详解

CISSP工作经验不足5年?助理级认证的进阶指南与实战策略 信息安全领域的新人常面临一个尴尬局面:虽然通过了CISSP考试,却因工作经验不足无法获得正式认证。这种"持证却不能名正言顺"的困境,让许多职场新人感到迷茫。实际…...

保姆级教程:手把手教你用Vector CANoe VT7001A给ECU供电(附CAPL脚本和Panel制作)

汽车电子测试实战:从零搭建VT7001A供电环境全流程指南 刚接触汽车电子测试的工程师,第一次看到VT7001A板卡时难免会感到无从下手——这块巴掌大的板子,既要给ECU供电,又要模拟各种故障场景,还要与CANoe软件联动。但别担…...

终极Unity资源编辑器:UABEA完整指南与实战教程

终极Unity资源编辑器:UABEA完整指南与实战教程 【免费下载链接】UABEA c# uabe for newer versions of unity 项目地址: https://gitcode.com/gh_mirrors/ua/UABEA 你是否曾为无法直接编辑Unity游戏资源而烦恼?是否想要深入了解现代Unity版本中的…...

重新定义内容获取效率:douyin-downloader如何实现300%性能提升的架构级解决方案

重新定义内容获取效率:douyin-downloader如何实现300%性能提升的架构级解决方案 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, an…...

别再问网管了!Win10手动设置固定IP地址,从查看到配置保姆级图文教程

Win10固定IP设置全攻略:从参数侦察到精准配置 每次遇到网络打印机无法连接或是NAS访问不稳定时,设置固定IP地址往往是解决问题的关键一步。但大多数教程直接跳转到配置步骤,忽略了最关键的环节——如何获取当前网络环境的正确参数。本文将带您…...

Dream-Creator:本地化AI图像生成工具的设计、部署与优化全解析

1. 项目概述:一个面向创意工作者的本地化AI图像生成工具最近在GitHub上看到一个挺有意思的项目,叫“Dream-Creator”。光看名字,你可能会联想到各种在线AI绘画平台,但它的定位很明确:一个开源的、可以部署在你本地电脑…...

[具身智能-453]:深度神经网络给了我们一种新的思维模式:噪声、波动、偏差、误差、错误、不完善、不完美,不再是抵制和消除的对象,而是系统泛化能力和应对未来不确定性的必要的组成部分。

深度神经网络引入了一种新的思维模式:噪声、干扰、波动、偏差、误差、错误、不完善、不完美,不再是要刻意抵制和消除的敌人,而是为增强系统泛化能力和应对未来的不确定性和未知世界的能力而主动引入的必要性和磨刀石。绝对的完美、精确和确定…...