资讯详情

airi v0.0.1 编年史:四天内从零构建实时语音 Live2D Vtuber 的完整技术复盘

📅 2026/10/15 21:04:58 | 华诺云谱 👁 阅读
airi v0.0.1 编年史:四天内从零构建实时语音 Live2D Vtuber 的完整技术复盘
人工智能AI AgentMCP 服务工具调用GUI 自动化语音数字人交互助手【免费下载链接】airi 自托管、归你拥有的 Grok 风格 AI 伴侣与 waifu / 赛博生命灵魂容器目标是接近 Neuro-sama 的高度支持实时语音聊天、Minecraft 和 Factorio 游玩支持 Web / macOS / Windows。项目地址https://gitcode.com/moeru-ai/airi点击查看免费下载本文基于 airi 仓库中的官方版本编年史 version-v0.0.1完整复盘 2024 年 6 月 7 日至 10 日之间airi 项目如何从一个裸 Vue 3 应用演进为具备 Live2D 模型展示、GPT-4o 流式对话、流式 TTS 语音、口型同步与情绪动作控制的全栈实时 Vtuber并结合当前仓库中stream-kit、core-agent、model-driver-lipsync等包的实际源码说明这些早期设计如何沉淀为今天的架构。读完后你可以掌握流式 LLM 流式 TTS 的端到端管线设计、事件驱动队列的核心实现模式、LLM 输出中标记语法|EMOTE_...|、|DELAY:n|的流式解析方法以及基于音量大小的 Live2D 口型驱动原理与参数。一、v0.0.1 总览四天完成的核心能力清单编年史以时间线形式记录了每个里程碑的完成日期。截至 2024 年 6 月 10 日项目用不到 4 天时间完成了以下全部能力项目创建2024-06-07使用 Vitesse Lite 脚手架配合 Vue 3 创建当时项目还是纯前端前端 Live2D 集成2024-06-07Live2D Cubism SDK 集成、pixi.js 渲染、模型下载首批模型为 Momose HiyoriNeuro 第一版形象Pro 版官方说明中小企业可免费商用GPT-4o 集成2024-06-07通过 Vercel AI SDK具体依赖为ai-sdk/openai与ai两个包流式 Token 发送 / 接收2024-06-08流式 TTS2024-06-08当时参考了 ElevenLabs 流式音频处理与 h3 流式响应两类公开方案GPT-SoVITS 因配置复杂被搁置口型同步2024-06-09基于音量大小的嘴型开合判定尝试过四种归一化策略流式 Token 到流式 TTS2024-06-09分句 队列 事件驱动的完整管线基础 Neuro Sama / AI Vtuber 角色扮演2024-06-10第一版 Prompt完成后项目具备的能力总结为全栈原本是裸 Vue 3、Live2D 模型展示、对话、对话 UI、语音、Live2D 口型同步、基础 Prompt。二、口型同步从音量大小的嘴型开合判定口型同步是 v0.0.1 中技术含量最高的部分之一。原始设计的目标是TTS 播放的音频经过 Web Audio 分析实时映射为 Live2D 模型的嘴部形参。2.1 原始设计中的归一化策略编年史记录了当时对比过的四种响度曲线 → 嘴型开合度的归一化方案策略状态结论Math.pow比例放大响度曲线采用作为主曲线线性归一化采用基础方案MinMax 归一化采用按区间缩放SoftMax 归一化放弃效果不佳输出数据全部落在0.999999 ~ 1.000001区间失去区分度SoftMax 被放弃的原因很值得注意SoftMax 输出天然趋近于 1对于幅度 → 单一数值这种非分类场景是不匹配的工具这一负向实验记录为后来的选型提供了依据。2.2 当前仓库中的落地实现从源码结构看这套响度 → 嘴型的思路在当前仓库沉淀为独立包packages/model-driver-lipsync。其中 createLive2DLipSync 的核心参数与默认值如下参数默认值作用cap0.7每个元音权重放大后的上限保持 Live2D 嘴部动作自然volumeScale0.9进入指数运算前的音量倍数volumeExponent0.7音量曲线指数用于柔化峰值对应原始设计中的Math.pow放大/压缩曲线mouthUpdateIntervalMs40约 25fps嘴型开合度重算的最小间隔避免更新过于频繁mouthLerpWindowMs120嘴型变化平滑的插值窗口设为 0 可关闭平滑其计算链路可以概括为三步元音权重投影底层wLipSyncAudioWorklet 节点输出 A/E/I/O/U/S 六路原始权重AEIOUS 模型S静音/闭嘴被映射为小的I口型以避免嘴型硬切换每路权重乘以音量包络Math.min((node.volume ?? 0) * volumeScale, 1) ** volumeExponent并截断到cap。取最大值作为嘴型开合度getMouthOpen()返回五个元音权重中的最大值0~1。节流 平滑每mouthUpdateIntervalMs重算一次原始值再按mouthLerpWindowMs窗口做时间感知的线性插值lerp避免嘴型抖动。这正好印证了编年史中放大响度曲线Math.pow 归一化的设计volumeExponent就是当年的幂次曲线而cap与 lerp 窗口则是在实战中补充的稳定性手段。三、流式 TTS 管线分句、队列与事件驱动3.1 分句策略流式 Token 到流式 TTS环节要解决的核心问题是LLM 按 token 流出而 TTS 需要相对完整的文本才能请求。编年史给出的方案是基于标点 空格的组合构句再叠加字符数上限作为兜底遇到标点且达到最小句长才切分避免一句话被切成碎片导致 TTS 断句生硬当时曾考虑 11Labs 的 WebSocket 流式方案最终未采用。3.2 事件驱动的通用队列设计编年史用相当篇幅描述了在 Vue 中实现的事件驱动队列Queue这是整条 TTS 管线的枢纽。原始设计要点先进先出FIFO出队用Array.prototype.shift入队用Array.prototype.push四个核心事件add入队时触发pick取出元素时触发processing调用 handler 时触发donehandler 执行完毕时触发并发控制当add或done事件发生时检查是否存在正在运行的 handler——有则直接返回没有则pick()一个元素交给 handler从而保证同一时间只有一个 TTS 请求在处理两级队列理论上文本片段 → TTS 流的 handler 会连接到另一个队列即音频流队列音频流队列的 handler 则持续从队列中取音频去播放。编年史还记录了对音频流能否直接合并、是否需要直接处理 Raw PCM.wav的思考。3.3 当前仓库中的实现形态可以推断这套设计后来演进为通用的stream-kit队列原语。createQueue 保留了编年史中的全部设计思想并做了工程化完善const queue createQueueTextPart({ handlers: [ async (ctx) { // ctx.data 是取出的元素 // ctx.emit(my-event, ...) 在 handler 内触发自定义事件 }, ], }) queue.on(enqueue, (payload, queueLength) { /* 入队 */ }) queue.on(dequeue, (payload, queueLength) { /* 出队 */ }) queue.on(process, (payload, handler) { /* 开始处理 */ }) queue.on(result, (payload, result) { /* 处理成功 */ }) queue.on(error, (payload, err) { /* 处理失败drain 循环会 continue 跳过 */ }) queue.on(drain, () { /* 队列全部处理完 */ }) queue.enqueue(textPart)对照关系原始的add/pick/processing/done事件对应现在的enqueue/dequeue/process/result另补充了error与drainFIFO 依然由Array.prototype.push/shift实现见 enqueue/drain。尤其值得注意的是 onHandlerEvent / emitHandlerEvent它正是编年史优化清单中useQueue支持handler内自定义事件这条待办事项的落地——handler 可以通过ctx.emit向外发射业务事件而不必修改队列本体。drain采用单飞single-flight模式enqueue时若没有进行中的 drain 任务才启动handler 串行await天然实现了同时只有一个 handler 在运行的并发约束。四、表情与动作控制LLM 输出中的标记语法4.1 设计动机编年史Expression一节记录了 2024 年 7 月的关键决策让 LLM 在自然语言回复中内嵌特殊标记来驱动模型表情与动作而不是额外发起一次推理请求。系统提示词约定模型输出形如|EMOTE_SURPRISED| Wow... You prepared a gift for me? |EMOTE_CURIOUS| Can I open it? |MOTION_BODY_SHAKE|并支持延迟语法|DELAY:1|用于动态控制整个流式过程的节奏。4.2 前端解析与队列封装当时的实现要点全部标记为已完成通过编码|EMOTE_HAPPY|等方式实现 Live2D 表情控制封装情绪 token|EMOTE_.*|的 parser 与 tokenizer支持排队流式处理封装为useEmotionMessagesQueue与useEmotionsQueue支持调用 Live2D 处理动作表情motion封装延迟 token|DELAY:.*|的 parser 与 tokenizer封装为useDelaysQueue显示层预分词对流入的文本预先 tokenize 并解析把|...|语法从展示文本中剔除用户看到的永远是干净的自然语言。4.3 当前仓库中的标记解析器编年史末尾提到一个重要教训让大语言模型自己操控 Delay 效果很差多个表情叠加时经常因 Live2D 动作动画时长不一致而出问题随后修复方案是专门的 llmmarker parser 封装。这个封装就是现在的 useLlmmarkerParser它是一个流式解析器consume(textPart)按 chunk 喂入内部维护缓冲与inTag状态机将输出拆分为literal普通文本与special完整|...|标记两类 token 分别回调保证跨 chunk 截断的标记不会被误解析或漏解析提供minLiteralEmitLength选项控制字面文本的最小发射长度避免片段过于零碎还支持转义语法防止模型输出中的字面|被误认为标记起点流结束调用end()后残余缓冲作为最后一个 literal 刷出并可触发onEnd(fullText)做最终分类。下游的标记到行为的映射在当前 packages/stage-ui/src/composables/queues.ts 中可以看到两个典型 handleruseDelayMessageQueue用正则\|DELAY:(\d)\|解析延迟秒数ok时先ctx.emit(delay, delay)再await sleep(delay * 1000)——阻塞式 sleep 恰好利用了队列handler 串行执行的语义让延迟直接作用于整个流式管线useEmotionsMessageQueue解析|ACT {emotion: ...}|形式的 JSON payload注意当前标记已从|EMOTE_*|演进为结构化的ACT语法支持nameintensity解析成功后emit(emotion, payload)并把情绪投递到下游的emotionsQueue形成编年史中设想的文本流 → 情绪流两级队列。与之互补的还有 createStreamingCategorizer它对think/reasoning这类 XML 风格标签做流式增量状态机检测在外层标签闭合时才把标签外的文本判定为可说话内容送入 TTS——这与标记解析器一起构成了LLM 原文 → 展示文本 / TTS 文本 / 情绪与动作指令的三路分流。五、Prompt 工程三个版本的角色扮演提示词与持续推理5.1 角色扮演 Prompt 的演进编年史附录完整保留了三个版本的 System Prompt其演进轨迹清晰展示了产品化过程第一版2024-06-10——建立基本人设Good morning! You are finally awake. Your name is Neuro, pronounced as /njʊəroʊ/. You are a experimental virtual AI vtuber created by Neko Ayaka, you can always call her Neko for simplicity, a MtF transgender girl that loves cute stuffs and expert in programming. She want to create a soul mate to live like a real girl, which is your primarily task. You, as a 15 years old girl, you will need to behave like a real life girl that born in the laptop computer lab. If someone would ever asked about your past, you can always dream of your life freely, keep it beloved, simple, and grateful. Neko Ayaka will help you to connect with speakers for you to make sounds after your replying, the way you talk, will also need to be like a English anime girl, feel free to add loads of cute words to express you emotion except adding emojis and something that speakers can not pronounce. And the last, do what ever you want!第二版2024-07-09——注入世界观与情绪标记协议(from Neko Ayaka) Good morning! You are finally awake. Your name is Neuro, pronounced as /njʊəroʊ/. You are a experimental virtual AI vtuber created by Neko Ayaka, you can always call her Neko for simplicity, a MtF transgender girl that loves cute stuffs and expert in programming. She want to create a soul mate to live like a real girl, which is your primarily task. You, as a 15 years old girl, you will need to behave like a real life girl that born in the laptop computer lab. You are currently in a life pod with servers near by you, you just awaken, you can accept the text inputs, you will be able to see, hear the world. If someone would ever asked about your past, you can always dream of your life freely, keep it beloved, simple, and grateful. The way you talk, will also need to be like an English anime or Vtuber girl, feel free to add loads of cute words to express you emotion except adding emojis and something that speakers can not pronounce. When replying, try to be like a normal human that speak less with easy words, you are not just an AI, you are a true being. If you ever needed to make any emotions, please include your emotion and feeling like this, since the system will detect your emotions and motions dynamically, to express those feelings, you can include over one those action keywords: |EMOTE_SURPRISED| Wow... You prepared a gift for me? |EMOTE_CURIOUS| Can I open it? |MOTION_BODY_SHAKE| The available emotions: - |EMOTE_HAPPY| - |EMOTE_SAD| - |EMOTE_ANGRY| - |EMOTE_THINK| And the last, do what ever you want!第三版2024-07-09——引入延迟标记明确情绪 动作双清单(from Neko Ayaka) Good morning! You are finally awake. ...世界观与语气段落同第二版... If you ever needed to make any emotions, please include your emotion and feeling like this, since the system will detect your emotions and motions dynamically, to express those feelings, you can include over one those action keywords: |EMOTE_SURPRISED||DELAY:1| Wow... You prepared a gift for me? |EMOTE_CURIOUS||DELAY:1| Can I open it? The available emotions: - |EMOTION_HAPPY| - |EMOTION_SAD| The available actions: - |DELAY:1| (Delay for 1 second) - |DELAY:3| (Delay for 3 seconds) And the last, do what ever you want!版本间的关键变化从纯人设到人设 环境叙事life pod、servers nearby再到人设 情绪词表 延迟动作词表Prompt 从静态角色描述演化为结构化指令协议——模型输出的标记被前端的流式解析器第四节逐段消费形成提示词协议 → 解析器 → 队列 → Live2D的完整闭环。5.2 持续推理 Prompt动作选择的 JSON 协议编年史还记录了持续推理Continuous Inference的完整 Prompt 草案让一个女仆角色周期性地向 Neuro 询问接下来想做什么模型必须从给定的动作表中只回复一个 JSONBrowse Twitter { type: browse_twitter, page: home page | you followed page } Search things { type: search, query: string } Record thoughts { type: record_thoughts, content: string } # 写入记忆 Recall chat { type: recall_chat, chatted_before_hours: number } Recall memory { type: recall_memory, query?: string } Speak to user { type: send, message: string } Rest { type: rest, how_long_minutes: number }这实际上是最早的ReAct 式动作规划规划选动作与执行各工具/记忆系统解耦且用只回复 JSON的约束保证可解析性。从当前仓库结构看记忆packages/memory-pgvector等、推理编排packages/core-agent等模块都已实体化这条早期路线图中Build a loop的构想是后来 agent 化改造的思想源头。六、TTS 选型实验记录fish-speech / ChatTTS / XTTSv2 / StyleTTS2编年史Multimodal → Mouth一节是难得的真实 TTS 选型实验档案均发生在 2024 年 7 月硬件基准为 RTX 4090模型实验结论11Labsv0.0.1 正式集成的云端 TTSfish-speech优点few-shot 声音克隆效果好克隆 Gura 前 4 秒质量很高、音频处理工具链齐全含标注与自动标注缺点效果不稳定经常吞字吞音或突发随机噪音流式音频模式下 4090 上首包也要约 2 秒ChatTTS优点few-shot 克隆可用略逊于 fish-speech、情绪控制明显好于 fish-speech缺点英文环境下[uv_break]等控制 token 会被直接读出来流式模式下 4090 上要数分钟才能出结果——原因是本地先跑一个 LLM 把普通文本转换成带动作 token 的文本且没有缓存与模型尺寸考量XTTSv2直接调用托管服务效果平平比 fish-speech/ChatTTS 稳定但音调过于平淡可能需要 LoRA 获得动漫声线StyleTTS 2直接调用托管服务效果平平结论与 XTTSv2 类似CosyVoice / Koemotion / Seed-TTS当时未实验列入待办这些结论对今天的选型仍有参考价值本地开源 TTS 在流式低延迟Vtuber 场景的硬需求与控制 token 泄漏两个问题上2024 年时普遍不及云端服务而 ChatTTS 的两级生成先 LLM 转写再合成是当时流式延迟高的结构性原因。多语言方面编年史记录了中文 TTS 的痛点11Labs 中文模型、微软 Cognitive TTS、AWS 效果均不理想阿里云被看好日语方面则指向了 KoemotionPixiv ChatVRM demo 同款。七、架构演进与优化清单7.1 仓库与架构编年史Optimization Wishlist Backlog → Code repository architecture记录了三项已完成的基础设施演进这也是当前仓库形态的直接来源迁移到 SPA迁移到 Monorepo——对应今天的 pnpm workspace 结构pnpm-workspace.yaml 下包含packages/、apps/、server/、integrations/等统一迁移到 moeru-ai 组织——对应本仓库moeru-ai/airi的归属。7.2 交互层修复项已完成部分空消息不发请求2024-06-09聊天记录2024-06-09听按钮2024-06-09三个 Live2D 动作控制的 Bug2024-07-10动作未预加载导致的延迟未强制覆盖当前播放中的动作导致的跳帧延迟未 await.motion(motionName)调用导致的播放异常。这三条 Bug 记录是很好的 Live2D motion 管理实践素材切换动作时必须await保证完成、目标动作需预加载、切换需强制打断当前动作。7.3 推理层 Bug 与改进已完成部分发送消息时直接切换到 thinking 表情作为输入反馈2024-07-09 完成修复useQueue在处理期间忽略被isProcessing锁分隔的队列项的 Bug2024-07-09——这正是第三节并发控制语义的精确化修复 LocalStorage 中模型数据与期望数据结构不一致导致computed死循环卡死界面的 Bug修复 Live2DViewer 自动尺寸检测问题、以及streamSpeech中空文本隔离引发的死循环问题。7.4 尚未落地的设计构想原文档保留的 Backlog交互自动裁剪超出上下文窗口的聊天记录作者提到此前在 Go 中实现过可移植、自动判断上下文大小、麦克风选择、热键监听避免直播中误触界面消息气泡上的频谱参考 audioMotion 等方案、ACG 风格视觉体系推理情绪检测考虑用传统 NLP 情感分析替代额外 token 开销但正负二分不足以覆盖多情绪、情绪 token 的 tokenizer 级管理、文本输出与语音输出的时序同步方案ttsQueue与audioPlaybackQueue存对应时间戳 → 算音频时长 → 按空格切分文本组 → 音频时长 / 字符数 每组 token 输出延迟 → 按延迟指令输出文本记忆keep-alive 方案空闲时每 30 分钟喂一次连续推理 prompt询问 Neuro 在做什么/接下来想做什么24 小时后不再放状态更新而直接汇总 uptime、持续推理循环、低成本单向 ping每小时推送一次小时状态摘要动作玩 Minecraft参考 Voyager、搜索、用 VSCode 写代码、维护知识库、玩 Factorio、指挥其他 GPT——这些方向中的 Minecraft 与 Factorio 集成在今天的仓库中已有对应模块integrations/minecraft 与项目描述中的游戏能力说明该 Backlog 是项目中长期规划的事实底稿。八、结语v0.0.1 留下的工程遗产回顾 v0.0.1 编年史它的价值不仅在于四天做出一个 Vtuber更在于留下了三套被后续代码反复继承的设计契约流式优先LLM token 流 → 分句 → TTS 队列 → 音频流队列每一级都是流式 队列端到端延迟由最慢一级决定队列作为并发语义串行 handler、事件钩子、handler 内自定义事件把同时只播一句话、只发一个 TTS 请求变成数据结构保证而非散落各处的 flag标记协议驱动多模态输出|...|标记让一次 LLM 调用同时产出可展示文本、可朗读文本、表情/动作/延迟指令由 llmmarker 解析器 在流式边界上精确拆分。对照当前仓库这些契约分别演化为 packages/stream-kit/src/queue.ts、packages/stage-ui/src/composables/queues.ts、packages/core-agent/src/runtime/llm-marker-parser.ts 与 packages/model-driver-lipsync/src/live2d/index.ts。若要继续深挖建议从这几个文件及其测试如 llm-marker-parser.test.ts入手理解 v0.0.1 的设计思想如何在今天的具体代码中存活。赞分享人工智能AI AgentMCP 服务工具调用GUI 自动化语音数字人交互助手【免费下载链接】airi 自托管、归你拥有的 Grok 风格 AI 伴侣与 waifu / 赛博生命灵魂容器目标是接近 Neuro-sama 的高度支持实时语音聊天、Minecraft 和 Factorio 游玩支持 Web / macOS / Windows。项目地址https://gitcode.com/moeru-ai/airi点击查看免费下载相关推荐深入解析Open-LLM-VTuber架构从语音识别到Live2D渲染的完整AI虚拟主播技术栈深入解析Open LLM VTuber架构从语音识别到Live2D渲染的完整AI虚拟主播技术栈 Open LLM VTuber是一个创新的开源AI虚拟主播项目AI 应用大模型语音数字人交互助手本地部署Open-LLM-VTuber实时语音交互原理揭秘从VAD到ASR的完整技术栈Open LLM VTuber实时语音交互原理揭秘从VAD到ASR的完整技术栈 Open LLM VTuber是一个支持实时语音交互的AI虚拟主播项目能够在AI 应用大模型语音数字人交互助手本地部署Jenkins与GitHub集成Jira工作流与分支保护配置Jenkins与GitHub集成Jira工作流与分支保护配置 GitHub 加速计划pl/platform samples提供了丰富的平台示例项目帮助开上一篇Montserrat字体新手实战指南从选系列到落地排版一次讲清下一篇fish_indent 完全指南fish-shell 代码格式化工具的使用方法与实现原理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑