Releases: nancheung/open-xiaozhi-client
Releases · nancheung/open-xiaozhi-client
v0.1.5
本版本进行了核心架构重构,使代码更稳定可靠,同时添加启动参数支持和改进版本检查。
✨ 新增功能
-
启动参数支持:支持通过命令行指定 OTA 地址和端口
open-xiaozhi-client-webui --ota http://server/ota --port 8080
-
外部访问:监听地址改为
0.0.0.0,支持外部访问。注意:必须要https -
实时版本检查:从 npm 注册表获取最新版本
🔧 架构改进
- 分层设计:将业务逻辑、适配器、UI 分离,降低耦合
- 状态机:用显式的状态机管理连接和对话流程
- 事件驱动:UI 通过命令分发而非直接调用
- 纯函数核心:业务逻辑零依赖,便于测试
🧪 质量提升
- 新增 200+ 单元测试,覆盖核心逻辑
- 所有测试通过(143 项)
- 生产构建验证通过
v0.1.4
本版本新增实时耗时分析面板,修复关键的录音异步竞态问题,进一步提升交互体验和调试能力。
✨ 新增功能
实时耗时分析面板
-
完整的时延可视化
- 在协议日志标签页下方新增专用的耗时分析面板
- 可视化每轮语音交互的关键时间点:
- 用户开始说话
- 用户说完话(STT 完成)
- 服务器进入说话状态(TTS 开始)
- 服务器停止说话(对话完成)
-
关键性能指标
- 端到端延迟:用户开始说话到服务器开始回复的总耗时
- 感知延迟(重点):用户说完话到服务器开始说话的等待时间
- 毫秒级精度,实时更新
-
便于诊断
- 快速识别系统中的性能瓶颈
- 对比不同模式下的交互延迟
- 服务端性能基准对标
🐛 Bug 修复
修复关键的录音异步竞态问题
背景:聆听状态下服务器主动关闭连接后,麦克风仍持续采集、日志持续出现 ↑ BIN 二进制数据
根因分析:
startRecording()是异步函数,包含多个 await 点(getUserMedia、addModule)- 连接关闭时
teardown()调用resetAudio()将audioStatus置为idle - 此时
startRecording中的 await 仍在进行中,refs 尚未赋值 stopRecording()发现 refs 为空,无可清理直接返回- 当 await 完成后,
startRecording继续执行,将 MediaStream 和 AudioWorklet 接好并启动 - 结果:
audioStatus已为idle但仍在持续录音,worklet 不停地写 ↑ BIN 日志
解决方案:引入录音会话代号(epoch)机制
startRecording()领取会话号,在每个 await 后校验会话是否仍有效- 若会话失效(epoch 已更新),则立即释放刚获取的麦克风轨道 / AudioContext 并退出,绝不接线 worklet
stopRecording()递增会话号,使任一进行中的启动作废- 保证了 worklet 启动的原子性和正确性
📊 性能与诊断
- 实时可见的系统端到端延迟,便于服务端性能对标
- 精细化的时间点记录,有助于识别语音处理链路中的瓶颈
- 支持多轮交互累积数据,便于性能趋势分析
🧪 质量保证
- 新增
LatencyChart、LatencyPanel单元测试 - 新增
latencySlice单元测试(时间点记录、时差计算) - 新增
useAudio竞态回归测试(确保 epoch 机制正确) - 所有 TypeScript 编译通过,无类型错误
v0.1.3
v0.1.3
本版本新增摄像头拍照功能,完善 OTA 连接和设备激活流程,并增强协议交互能力。
✨ 新增功能
摄像头拍照能力 (self.camera.take_photo MCP 工具)
- 完整的视觉交互链路:WebUI 调用摄像头采集 → JPEG 抓拍 → POST 到视觉端点 → 服务端返回分析结果
- 摄像头采集模块 (
src/features/camera/cameraCapture.ts)- 基于
getUserMedia实时采集视频流 - Canvas 2D 绘制和 JPEG 压缩抓拍
- 自动清理和资源释放
- 基于
- 摄像头管理状态切片 (
src/features/camera/cameraSlice.ts)- 摄像头启用/禁用状态
- 拍照进度和错误处理
- MCP 工具实现
- 解析服务端初始化时下发的
capabilities.vision.{url, token} - 工具签名:
self.camera.take_photo(question: str) → analysis_result - 抓拍后以
multipart/form-data格式发送:question + JPEG 图片 - 异步等待服务端视觉分析结果
- 解析服务端初始化时下发的
- 摄像头实时预览面板(设备 Tab)
- 实时视频预览
- 拍照按钮和状态提示
- 连接断开时自动释放摄像头
- 完整的单元测试覆盖
src/features/mcp/__tests__/tools.test.ts- 拍照工具测试src/ws/__tests__/wsManager.test.ts- 摄像头初始化和清理测试
OTA 连接完善
- 系统信息补齐 (
src/features/connection/systemInfo.ts)- OTA 请求头:
Activation-Version,User-Agent,Accept-Language - OTA 请求体:version、language、mac_address、uuid、chip_model_name、application、board
- 提供更完整的设备身份信息,便于服务端识别和配置下发
- OTA 请求头:
- 设备激活轮询流程 (
src/features/activation/activate.ts)- 自动检测激活消息中的
challenge字段 - 触发 POST
/activate轮询流程 - 按 HTTP 200(激活完成)或 202(继续轮询)响应码处理
- 激活完成后自动继续建立 WebSocket 连接
- 自动检测激活消息中的
abort 交互增强
buildAbort()现支持可选的reason参数- 支持传递
"wake_word_detected"等原因码,便于服务端记录中断原因
🧪 质量保证
- 所有新功能覆盖单元测试
- TypeScript 严格模式下
tsc -b编译通过 - 摄像头资源泄漏防护:WebSocket 断线时自动释放
📦 依赖
无新增依赖。
统计
- 3 个 commits
- 11 个文件修改/新增
- ~550+ 行代码变更
兼容性
- 需要支持
getUserMedia和 Canvas 2D 的浏览器 - 服务端需支持
capabilities.vision下发和/activate轮询端点
v0.1.2
本次版本聚焦于 WebUI 交互体验升级、音频模式完善、设备控制统一化,同时补齐了多项稳定性修复与发布准备工作。整体上,客户端在 响应式布局、实时语音交互、设备设置管理 方面都有明显提升。
✨ 新增特性
1. 完整实现三种音频监听模式
- 完善 Auto / Manual / Realtime 三种监听模式的行为逻辑。
- Auto 模式 下,TTS 播放结束后可自动恢复监听,更贴近半双工语音助手体验。
- Realtime 模式 下支持播放 TTS 时持续录音,实现更自然的全双工对话。
- 在 TTS 过程中,用户可以更直接地打断并开始新一轮语音输入。
2. 全新响应式 ClientView 布局
- 重新设计主界面,支持 窄屏/宽屏自适应布局。
- 窄屏下采用更紧凑的状态条、对话区与底部控制栏布局。
- 宽屏下升级为 双栏布局:左侧对话历史,右侧命令中心,信息层次更清晰,调试和交互效率更高。
3. 新增统一设备设置面板
- 使用新的 DeviceSettingsPanel 替代原有 IoT 面板。
- 集成 音量、亮度、主题 等设备设置。
- 抽离统一的设备设置入口,方便 UI 与 MCP 工具共用同一套控制逻辑。
4. 设备设置与面板布局持久化
- 设备的 音量 / 亮度 / 主题 现在支持本地持久化。
- 调试面板布局比例也会自动保存,下次打开可恢复之前的使用习惯。
5. 音频可视化体验增强
- 音量条和波形图支持 响应式尺寸适配。
- Canvas 分辨率会随容器尺寸同步更新,提升不同屏幕下的显示质量和清晰度。
⚡ 优化改进
- 优化窄屏布局下的交互细节,提升输入反馈和音频状态展示的一致性。
- 活跃音频状态下,将模式切换图标替换为更直接的 中断/Abort 按钮,减少误操作成本。
- 优化窄屏与宽屏场景下的 STT/TTS 展示逻辑,更清楚地反映“用户在说”和“服务端在回应”的并行状态。
- 协议日志时间戳精确到 毫秒,便于排查时序问题。
- 日志中的播放按钮改为内联显示,界面更紧凑。
- README、截图、功能说明、开发指引与路线图同步更新,补充 License 和 npm 发布信息。
🐛 Bug 修复
- 修复 Realtime 模式 下上下行音频流在协议日志中无法独立正确合并的问题。
- 修复连接关闭后录音未在所有路径下正确停止的问题,避免麦克风与 AudioContext 残留占用。
- 修复 Realtime 模式下停止麦克风时发送错误控制指令的问题,改为正确发送
abort。 - 修复部分音频状态切换场景下自动恢复监听行为不准确的问题,减少异常重启或错误中断。
📦 其他
- 版本更新至 v0.1.2
- 补充项目 License
- 更新发布配套文档与展示素材
v0.1.1
更新内容
新功能
- 新增 Conversation History 气泡式对话历史区域,并将其挂载到 STT / TTS 区域下方,方便查看完整对话过程。
- 引入独立的对话状态管理,并将其接入 WebSocket 与音频链路,使聊天记录展示更稳定、上下文更清晰。
- 优化协议日志展示方式:连续的二进制 Opus 音频帧会自动合并显示,减少日志刷屏,并支持在消息日志中直接回放音频。
- 将原有的虚构 MCP mock 工具替换为基于真实浏览器能力的实现,包括音量控制、主题切换、亮度调节、设备状态获取、系统信息获取、页面重启以及固件升级链接打开等能力。
- 将固定宽度面板升级为 react-resizable-panels,支持更灵活的界面布局调整。
- 服务地址输入改为直接填写完整 OTA URL,减少连接配置歧义。
- 应用版本号改为动态注入,确保界面显示、运行时信息与发布版本保持一致。
- 增加版本更新检测相关能力,为后续发布与升级流程提供支持。
修复与优化
- 修复了 react-resizable-panels v4 的 API 适配问题,确保布局组件按预期工作。
- 修正了对话历史面板尺寸配置以及助手消息文本来源问题,避免左侧面板异常变窄,并提升历史记录展示准确性。
- 优化助手消息在
tts-start相关生命周期中的处理逻辑,提升播放过程中回复气泡的稳定性。 - 抽离并复用
useAudioPlayback播放逻辑,同时调整消息日志中的播放按钮交互与文案,提升音频回放体验。
发布与工程化
- 新增 npm 发布工作流,完善发布自动化流程。
- 项目版本更新至 0.1.1。
- 补充本地 worktree 忽略规则,减少本地开发环境对版本控制的干扰。
完整更新
Compare: v0.1.0...221998c
v0.1.0
v0.1.0
基于 Web 技术实现的小智 AI 客户端,通过 WebSocket 协议与小智设备通信,支持实时语音对话。
功能
实时语音通话
- 基于 AudioWorklet 实现低延迟麦克风录音与扬声器播放
- 使用 Opus 编解码器(opusscript / WebAssembly)对音频流进行实时编解码
- 录音侧实时音量条(VolumeBar)、AI 回复侧波形动画(WaveformBars)可视化反馈
- 支持麦克风多种监听模式切换
WebSocket 连接管理
- 完整实现小智 WebSocket 协议,覆盖
hello/listen/tts/mcp/iot消息类型 - 连接状态机:未连接 → 连接中 → 已激活 → 通话中
- 设备 ID 自动生成,支持手动配置;连接配置与界面设置持久化至
localStorage
协议调试面板
- 实时展示所有 WebSocket 消息,方向着色区分收发
- 自定义 JSON 发送面板(Ctrl+Enter 快捷发送)
- IoT 指令描述符编辑器与接收指令列表
- HTTP 面板支持
update_config/restart服务端操作 - 设置面板可调整
hello握手参数、音频配置、连接超时
npm 发布
- 包名
open-xiaozhi-client-webui,支持npx一键启动
技术栈
Vite · React · TypeScript · shadcn/ui · Tailwind CSS · Zustand · AudioWorklet · opusscript (WebAssembly)