开源AI虚拟人项目:结合大模型、语音与2D骨骼动画,一分钟接入

发布时间:2026/10/22 10:30:53
开源AI虚拟人项目:结合大模型、语音与2D骨骼动画,一分钟接入 这个国庆我基本没出门把自己关在屋里干了件特别“不理智”的事给开源社区交出一个半成品虚拟人项目代号就叫X。你可以叫它AI虚拟伴侣也可以开玩笑叫它“AI老婆”。本质就是一个能聊天、能听说话、会眨眼、嘴型能对上语音的数字人网页应用接上大模型和语音服务后从克隆代码到对着它喊一句“你好”严格来说一分钟内真能跑起来。做这件事的起因很简单我想要一个能挂在浏览器里的陪伴型角色而不是又一个只懂文字回复的聊天机器人。项目核心是用在线大模型API做对话大脑套上语音识别和语音合成再配一套2D骨骼动画外形最终封装成网页SDK和后端API。适合独立开发者、想做虚拟主播或客服的团队、还有那些想在硬件屏幕上塞一个虚拟助手的朋友。整套东西没有用特别冷门的技术也没有强行上多复杂的网络架构主打就是拆开简单、装上快、能按需改人设。这篇文章我会把设计思路、技术选型、一分钟接入步骤、角色记忆和token成本控制还有七天里踩过的坑全写出来希望能帮你少走点弯路。1. 为什么花七天做这件事需求与设计思路1.1 “AI老婆”到底是不是老婆标题里的“AI老婆”就是个噱头更像是朋友之间的调侃。实际做出来的东西是一个可自定义角色性格的数字人陪伴应用。它没有实体不卖感情只做一件事用语音或文字跟你聊天同时配上表情和口型动作让你觉得对面不是一个文本框而是一个活生生的角色。我设计时把它的定位拉得很明确陪伴型虚拟助手。你可以把它的性格改成温柔知性也可以改成冷幽默程序员甚至把它变成一个客服数字人。核心不绑定“老婆”这个身份而是一套可以套任意角色的框架。“老婆”只是我在国庆期间测试时用的一个临时人设。这里有个很重要的产品判断用户对纯文字聊天已经疲劳了为什么要多做一层数字人形象因为声音和表情会带来额外信息同样一句“我在呢”配合微笑和眨眼比纯文字更能让人觉得被回应。这种“存在感”是聊天机器人做不出来的。1.2 七天时间、几十亿token的真相标题说“肝了七天七夜”这话不夸张但也不是完全不吃饭不睡觉。七天里我每天大概高强度工作十个小时左右中间还推掉了几次线上聚会。整个项目并不是从零手写所有东西而是把大模型API、语音服务、开源动画渲染方案拼装起来再围绕“角色体验”做深度集成。“花了几十亿token”是典型的程序员式夸张。真实情况是七天里我在调试对话、跑测试、生成摘要和反复改提示词上消耗了大约几千万token。几十亿这个数字是节目效果但也侧面说明一点大模型应用的成本大头不是正式跑起来之后而是开发过程中不断试探、重试、对比方案时烧掉的。这部分钱很多人容易忽略。七天的节奏大致是这样的第1天做技术选型确定虚拟人形态第2天到第3天接大模型对话和基础人设第4天到第5天做语音识别、语音合成和数字人形象整合第6天解决记忆与上下文问题第7天打磨口型同步、写文档、整理开源包。这七天最深的体会是真正花时间的不是“接API”而是“让几个模块协同工作时像一个人”。语音识别结束语和对话引擎的停顿逻辑如果没配合好听起来就像一个反应慢了半拍的木偶。后面我会细说这些坑。2. 技术选型与一分钟接入的架构密码2.1 拆成五个可替换模块我一开始就把项目拆成了五个独立模块目的只有一个每个模块都能单独替换。很多所谓“AI虚拟人”项目做死就是因为对话、声音、形象强耦合想换一个TTS服务商结果要去改前端渲染代码。五个模块分别是模块职责可替换选项对话引擎理解用户输入、生成回复、输出情绪标签任意兼容标准API的大模型服务语音识别把麦克风声音转成文字在线ASR服务或本地小模型语音合成把回复文字转成语音在线TTS服务支持SSML最好形象渲染显示虚拟人、驱动表情口型2D骨骼动画、3D模型、纯前端生成会话管理保存历史、记忆、上下文窗口Redis、SQLite、内存存储这种模块化设计让“一分钟接入”成为可能。用户不需要理解全部门道只需要知道自己用哪家的大模型、哪家的语音在配置文件里填好密钥就能跑。我不希望使用者为了换个声音还得去看前端JavaScript代码。2.2 为什么认准在线大模型API而不是本地模型我身边有不少人第一反应是“为什么不跑本地模型非要花钱买API”。这个问题的答案很现实本地模型需要显卡、需要调显存、需要会部署推理框架任何一个环节出了问题七天根本不够用。我只想做一个体验完整的虚拟人不是在国庆假期重写推理引擎。在线大模型API的最大优势是质量稳定和接入成本低。像角色扮演、情绪感知、自然口语这些能力头部API服务已经打磨得很成熟。你只需要把系统提示词写清楚就能拿到不错的回复质量。本地模型当然也能做但要达到接近的效果显卡成本和调优时间会成倍上升。另外“一分钟接入”这个承诺本身就要求我不依赖复杂的本地环境。用户只需要有Node.js环境、一个API密钥、能上网就能跑起来。如果强行要求本地必须有GPU那标题就得改成“国庆肝了七天七夜开发出AI老婆虚拟人需要三万元显卡才能玩”。当然我也预留了本地模型接入接口。任何人想切换成本地推理只要实现一个简单的对话函数能输入消息数组并返回文本和情绪标签其他模块完全不用动。这样既保证了开箱即用也照顾了喜欢折腾的开发者。2.3 数字人形象没有摄像头也能“活”起来虚拟人形象方案我对比过几个方向视频合成真人形象效果最好但需要大量算力和素材不现实3D建模加实时渲染好看但制作周期长开源角色模型也偏少2D骨骼动画加表情差分制作相对简单动作自然适合网页场景。我最后选了2D骨骼动画方案因为它对设备要求低一个浏览器就能跑而且社区里有很多可免费使用的角色素材。形象不是重点重点是它能不能“配合说话”。我做了三个关键动作眨眼、微笑随语气变化、嘴型随语音开合。表情这一块没有用什么高深算法。我在对话引擎返回内容里约定了一个emotion字段取值包括happy、caring、neutral、thinking。前端根据这个字段切换角色的表情组合。比如用户说“我今天被领导骂了”模型返回emotion: caring虚拟人就会自动变成微微皱眉、眼神温柔的形态比面无表情念回复强太多了。嘴型同步是另一个复杂点。简单方案是根据语音播放的音量大小控制嘴部开合度音量高嘴张大音量低嘴变小。好处是稳定、通用、不需要额外数据坏处是细微口型不可能绝对准确。七天里我试过用TTS返回的拼音时间戳做精确驱动效果确实更好但很多语音服务不提供这个能力最后我保留了两套驱动方式默认音量驱动支持按需扩展。2.4 接入层设计为什么能做到一分钟“一分钟接入”不是一句空话它由两部分决定一是本地启动足够简单二是对外暴露的接口足够薄。项目启动走的是极简路线下载代码、安装依赖、配置环境变量、运行一条启动命令。所有依赖都锁好版本不会出现昨天能跑今天报错的情况。默认监听本机端口浏览器直接打开就是完整页面不需要单独构建前端工程。对外接入方面我做了两种方式。第一种是后端API模式其他服务只要用HTTP调我的接口传入文本或音频返回回复文本和情绪标签就能把虚拟人能力嵌入到任何系统里。第二种是网页SDK模式你要在自家页面里嵌入一个虚拟人只需要引入一个脚本文件和一行容器节点SDK会自动处理界面渲染、音频播放、WebSocket连接和断线重连。我对SDK的最小化执念很强。接入代码一定要控制在一分钟以内超过一分钟就是我的设计失败。所以所有复杂的东西都收进SDK内部使用者什么都不用关心。3. 实操一分钟接入完整步骤3.1 环境要求与初始化先说环境要求。你需要准备一台能联网的电脑装好Node.js 18及以上版本然后准备一个大模型API的密钥以及语音识别和语音合成的密钥。如果暂时没申请语音服务项目也支持纯文字模式先用文字把整套流程跑通后面再补语音。初始化步骤非常简单打开终端执行git clone https://example.com/x-virtual-human.git cd x-virtual-human npm install cp .env.example .env这里所有配置文件都集中在.env文件里。打开它你会看到类似这样的内容# 大模型API配置 AI_API_KEYsk-你的密钥 AI_BASE_URLhttps://api.example.com/v1 AI_MODELchat-model-name # 语音识别配置 ASR_API_KEY你的ASR密钥 ASR_BASE_URLwss://asr.example.com # 语音合成配置 TTS_API_KEY你的TTS密钥 TTS_BASE_URLhttps://tts.example.com # 服务端口 PORT3000填好后保存直接运行npm start看到控制台输出“虚拟人已启动访问 http://localhost:3000”就说明成功了。浏览器打开页面第一眼会看到一个虚拟角色站在淡色背景里左下角有麦克风按钮和文字输入框。点击麦克风说一句话等两秒它就会用语音配合表情回复你。整个过程不需要编译不需要跑数据库迁移不需要加载模型文件。我第一次在没有文档的情况下帮朋友部署从拿到代码到对话成功确实只用了不到一分钟。3.2 配置角色人设不让它一张嘴就露馅默认角色是个通用助手但我想让大家拿到手就能改出自己的个性。项目里提供了一个角色配置文件character.json结构很直白{ name: 小影, personality: 温柔但有主见说话简短带一点点幽默感, background: 一个住在浏览器里的虚拟人喜欢看书喜欢听用户讲日常, speak_style: 用口语短句回复语气自然不要书面语, greeting: 嗨你来啦。今天想聊点什么 }系统会把这份配置自动翻译成模型能理解的系统提示词。如果你想更精细地控制可以直接编辑system_prompt.txt里面是真正发给大模型的原始提示词。我建议在personality字段写清楚“什么能做、什么不能做”比如“不要自称AI不要讲大道理每次回复不超过三句话”效果会非常明显。这里有一个关键细节很多新手的默认人设会写成“你是一个温柔可爱的女孩子”这句话信息量太少。模型不知道什么叫温柔可爱你需要给它具体的行为样本。我在提示词里加了一组对话示例告诉模型遇到不同场景该怎么说话。比如用户说“今天好累”示例回复是“那就别硬撑了把脚翘起来跟我说说发生什么了”。有了具体例子之后角色性格瞬间就立住了。3.3 语音链路怎么开起来文字模式跑通后就可以开语音。语音链路涉及两个方向识别用户说什么合成虚拟人回答什么。麦克风采集由前端负责浏览器原生的MediaRecorder接口就能解决。录制完成后把音频文件传给后端的ASR接口识别成文字再丢给对话引擎。对话引擎返回文本后端把文本发给TTS服务合成音频返回给前端播放。如果你希望延迟更低可以把“录制完整句话再识别”改成“边录边识别”。代码里已经做了切换开关默认走稳妥路线延迟约两秒想追求流畅可以打开流式ASR整体能缩短到一秒以内。不过流式方案对网络稳定性要求更高开发阶段建议先关掉。3.4 嵌入到自有页面除了直接打开网址使用项目还提供了一个给宿主页面引用的SDK。嵌入思路很简单在自己网页里加一个div然后加载SDK脚本传一个后端地址就行了。div idvirtual-human/div script srchttps://your-server.com/sdk.js/script script VirtualHuman.init({ container: #virtual-human, serverUrl: https://your-server.com, theme: light, autoGreeting: true }); /scriptSDK会自动创建虚拟人窗口包括角色的形象、表情画布、麦克风按钮和文字输入框。对宿主业务来说SDK把自己彻底封装成一个黑盒你只需要关心如何把用户身份传给后端以便读取对应的记忆数据。我特意让SDK不绑定前端框架原生JavaScript实现React、Vue页面都能直接引入。4. 角色塑造与长期记忆的核心实现4.1 人设怎么写才不像机器人很多人以为人设就是“设定性格词”其实远远不够。我踩过的最大坑是提示词写太薄模型开始自由发挥说着说着就变成了AI客服口吻。后来我总结出一个可复用的人设模板包含五个要素身份定位角色是谁、住在哪、和用户是什么关系性格表现不是抽象词而是具体行为习惯说话方式短句还是长句是否使用口语词回避边界哪些话题不回答、如何拒绝情绪反馈用户开心/难过时分别怎么表现。模板代码我放在了prompt_templates目录里。其中“回避边界”很重要虚拟人不能什么都说也不能变成纯情感垃圾桶。你要给它一条礼貌的退路比如“如果用户提到现实中的私人隐私提醒他注意安全并转移话题”。这既保护用户也保护项目。4.2 记忆系统三层结构虚拟人如果没有记忆每次对话都是“第一次见面”陪伴感会大打折扣。但记忆又不能全塞进上下文否则token消耗涨得飞快。我设计了三层记忆体系。第一层是短期记忆也就是最近20条对话原文。这层直接放进大模型上下文保证它能理解前因后果。第二层是会话摘要每当对话轮数达到10轮就触发一次摘要生成把前面的讨论浓缩成一百字以内的记录存进会话数据里。第三层是长期记忆库把用户明确的偏好、经历、重要事件抽出来按类型存进SQLite表每次对话开始时检索最相关的几条注入提示词。举个例子。用户说“我养了一只猫叫年糕”长期记忆模块会识别出“宠物”和“名字”信息写入数据库。下次对话时系统检索到相关记忆就会在提示词里自动加上“用户养了一只猫叫年糕”虚拟人自然会问“年糕最近有没有拆家”。这种细节就是陪伴感的来源。4.3 Token成本怎么控制下来标题里的“几十亿token”虽然是玩笑但token消耗确实是虚拟人类项目最大的隐形成本。我做了几组估算和优化放出来供参考。假设普通用户每天对话100轮每轮双方加系统提示词约1000 token一天的token消耗大约是10万。按市面上主流大模型API的中等定价折算下来一天大概几块钱一个月一顿火锅钱。但如果提示词写得不克制每轮塞进5000 token历史加各种背景设定成本会直接翻五倍。我总结的成本控制原则有三个上下文窗口设置上限默认只保留最近6轮完整对话长期记忆不是全量注入而是通过关键词检索取最相关的三条相同问题开启简单缓存比如用户重复说“你叫什么”直接返回历史结果不走模型。代码里暴露了MAX_HISTORY_ROUNDS和MAX_MEMORY_ITEMS两个配置项方便你根据自己的预算调整。我还加了一个“当日token统计”面板可以直观看到每次对话花了多少token避免月底账单吓人。4.4 多模态联动语气、情绪和动作怎么串起来虚拟人让人“觉得活”的关键在于回复的文字、语音的音调、形象的表情这三者是同步的。我定义了一套轻量交互协议对话引擎返回的JSON格式统一如下{ reply: 今天有点累了吧我陪你说会儿话。, emotion: caring, action: head_tilt, memory: user_tired_today }前端拿到emotion会切换表情拿到action会触发一个骨骼动画动作比如歪头、挥手、思考。这些动作定义在animations.js里可以自行增删。因为动作和表情是数据驱动所以不限于“AI老婆”人设客服人设也可以做“点头查看工单”之类的动作。这里最值得说的是“记忆写入”字段。某些对话不需要写入记忆的模型就不输出这个字段一旦输出后端会解析并存储到对应兴趣点。最初我想让模型每次都写记忆结果连“今天天气不错”都被当成偏好存了下来记忆库变得很脏。后来改成模型只在确实涉及用户偏好、重要事件时才输出memory字段效果干净很多。5. 踩坑记录七天里真实遇到的五个问题5.1 语音延迟为何降不下来第一天接完语音整个链路跑通后我特别兴奋结果自己体验了三次就想删项目。原因太明显了录音结束等ASR识别等大模型生成等TTS合成一层层叠加总延迟能到五六秒。这种体验根本没法用。解决办法是三步优化。第一步ASR切流式不用等用户说完再去识别而是边录边出中间结果用户停顿后直接提交最终文本。第二步TTS返回音频流后前端边下载边播放不用等服务端把整个音频文件收完。第三步把大模型返回的“首字延迟”也纳入监控如果某个API服务首字超过800毫秒就告警。优化完整体延迟稳定在两秒内虽然还没到真人对话水平但已经能正常聊天了。5.2 WebSocket断连和内存泄漏前端和服务器保持一条WebSocket长连接用来推送虚拟人的状态变化。开发中我发现手机锁屏再打开连接经常断而且过一段时间后服务器内存占用涨得很高。根本原因有两个。一是连接没有心跳保活网关会回收空闲连接。我每隔30秒发送一次Ping并让服务端回Pong锁屏后连接也能存活。二是服务端在保存历史会话时把每次对话的所有对象都放在内存里没有及时释放。我改成了按用户ID定期把历史序列化到SQLite并在固定时间窗口后丢弃。这里强烈建议所有做实时应用的人都加上心跳机制否则线上问题会隐藏得很深。5.3 口型乱动嘴像装了马达音量驱动口型看起来简单实际有个坑TTS合成的语音开头和结尾经常有很轻的气音音量波动也很随机如果直接把音量映射成嘴型开合度虚拟人的嘴会高频抖动看起来特别廉价。我加了一个两层过滤器。第一层是音量平滑用滑动窗口平均音量避免单帧异常波动第二层是静音阈值低于阈值时强制闭嘴。经过调整后角色说话时的嘴型终于稳定下来停顿的时候也不会乱动。调完这个我意识到很多“一眼假”的数字人问题不是出在模型不够强而是这些动态细节没人打磨。5.4 常见问题速查表问题可能原因解决方法启动后页面空白端口被占用修改.env里的PORT或者执行lsof检查占用进程说话没有声音TTS密钥未配置或浏览器自动播放被拦截检查控制台报错引导用户点击页面后再播放语音回复语气像客服人设提示词太弱增加对话示例写清楚说话风格和边界token消耗异常高历史窗口太大或记忆注入过多调小MAX_HISTORY_ROUNDS检查记忆检索逻辑角色不说话流式发送文本格式错误核对接口返回确认是否走了SSE协议虚拟人形象不动WebSocket未连接查看网络请求确认ws地址正确并检查心跳5.5 一个意外收获它不只适合“老婆人设”开源之后有朋友把它改成了一个“虚拟图书管理员”还有团队尝试改成售前客服。这让我意识到项目真正值钱的地方是“角色人格化封装方法”。底层大模型只是底座怎么把性格、记忆、语音、表情组合成有温度的角色才是核心。如果你想把它改造成客服只需要做三件事把人设提示词换成产品知识库问答风格把长期记忆改成工单标签和用户画像再把情绪标签换成“耐心、礼貌、专业”。后端接口不用动前端表情可以少一些整个改造在一天内能完成。这也解释了为什么我在架构上坚持模块化而不是做死成“AI老婆”。6. 从开源到现在我的一些真实体会项目做完后我没有急着加更多功能而是花了一天时间把文档写清楚尤其是“接入时最容易出错的地方”。我始终觉得开源项目如果只有代码没有文档价值会少一半。每一条配置项我都写了注释每个接口都给了请求示例。这次国庆开发的经历让我有几个很实际的感受。第一做AI类项目不要一开始就追求复杂。先用现成的API把完整流程跑通体验比什么都重要。第二技术栈越稳越好我用的是社区里最成熟的方案虽然显得不够炫但七天能交付就是赢。第三虚拟人这类产品细节体验决定成败。同样一句回复加一个停顿、一个表情、一个记忆点给用户的感受就完全不一样。最后分享一个小技巧如果你拿这个项目做演示千万记得在开始前清空数据库里的历史对话和缓存。我吃过亏有一次给别人演示虚拟人突然说“刚才你不是说要去看牙医吗”实际上那是前一天我自己测试时说的话。临时清理的脚本我放在了tools/clean_memory.js里一行命令就能把角色重置为初次见面状态。这次代码已经全部开源仓库名我在这里就不报了免得像广告。如果你在开发虚拟人、智能客服或任何需要“人格化对话”的项目欢迎直接拿这套框架去改。改人设、换声音、加动作都是几行配置的事情。希望这个国庆的七天也能帮你省下后面很多个七天。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询