RealTimeTalk:一个实时数字人对话系统的工程实践

2026年上半年,大模型的能力边界从"能聊天"迅速扩展到"能干活",但大多数AI对话产品仍然停留在纯文本交互的阶段。用户打字,模型回字,上下翻屏------本质上是把2023年的ChatGPT体验原样搬到了各种垂直场景里。

这里缺了一环:声音和形象。 人类之间的沟通,语气承载情绪,表情传递态度。当AI只能回文字时,它只是工具;当AI能开口说话、有可视形象时,它才开始像一个对话伙伴。但要把"文本回复"变成"数字人说话"的完整体验,中间隔着的不是一两个API调用,而是一条端到端的实时音视频管线。

RealTimeTalk 正是围绕这个问题构建的:一个支持实时对话、语音合成与数字人视频播报的Web应用,从LLM推理到TTS合成再到avatar视频播放,形成"边生成、边合成、边播放"的端到端流水线。该项目已在生产环境中稳定运行,验证了整套技术方案的可行性。


一、问题与背景

拆开来看,"数字人实时对话"至少需要五个环节串联:用户输入→LLM推理→文本分段→TTS语音合成→avatar视频匹配与播放。每个环节都有各自的工程难点。

LLM推理的延迟,是第一个瓶颈。如果等模型生成完整回复再开始合成语音,首帧延迟至少是推理时间加合成时间之和,用户感知到的"对方在思考"的空白期会显著拉长。TTS合成的速度与并发控制,是第二个瓶颈。长回复需要拆分多段分别合成,拆分策略既要考虑语义完整性,又要考虑单段时长与播放体验的平衡。avatar视频的匹配与切换,是第三个瓶颈。数字人的口型、表情与语音的对应关系需要语义分析来驱动,而视频片段的预加载、缓存与无缝切换又涉及前端的媒体调度。

更复杂的是,这五个环节不是串行完成再一次性交付的,而必须在第一段语音就绪时就立即推送播放,同时后台继续生成后续段落。这就要求整个系统是一个流式管道,而不是批处理作业。此外,对话的持续性还引入了会话管理的复杂度------多轮对话需要维护上下文窗口,而长对话会导致token消耗线性增长,必须通过智能摘要机制在信息保留与成本控制之间取得平衡。RAG知识检索的引入进一步增加了变量:检索到的文档片段如何与对话上下文融合、检索失败时如何降级、不同角色的知识库如何隔离------这些都不是单次API调用能覆盖的工程问题。


二、产品规格

RealTimeTalk 的产品形态是一个Web端对话应用:左侧是数字人形象区域(虚拟avatar视频播放),右侧是聊天面板(对话气泡)。用户输入消息后,系统经历四个状态切换:

Idle(待机):数字人播放呼吸态循环动画,等待用户输入。

Thinking(思考):数字人切换为分析动画(play_analysis),聊天面板显示思考状态。

Speaking(说话):流式管道推送首个语音段落,数字人切换为说话视频片段,聊天面板同步展示逐字气泡(bubble_char),用户感知为"对方正在边说边想"。

Bridging(段落衔接):一个说话段落播放完毕,下一段尚未就绪时,数字人短暂回到分析动画,避免黑屏或静止。

会话状态由Redis持久化,支持断线重连时恢复上下文。媒体资源通过MinIO对象存储管理,支持预签名URL访问。知识库管理后台独立于对话页面,基于Qdrant向量数据库提供RAG检索能力,允许管理员上传、索引和管理领域知识文档。


三、技术架构

系统采用前后端分离 + Docker Compose多服务编排的架构。技术栈选型如下:

后端:FastAPI(Python),以异步协程驱动全链路。核心分层为api路由层(REST + WebSocket)、agent对话引擎层(LLM调用 + RAG注入 + 对话历史管理)、pipeline流式管道层(文本分段 + 段落生成 + 确认式推送)、services外部服务封装层(LLM/TTS/Embedding/Qdrant/MinIO/Redis)。

前端:React + Vite + TypeScript,双入口SPA架构(主对话页 + 管理后台)。核心组件包括AvatarView虚拟形象播放器(双video叠加架构,主视频播segment、循环视频播idle/analysis,通过activeElementRef跟踪可见元素、thinkingModeRef/pendingSrcRef防竞态)、ChatPanel聊天面板(自动滚动至最新消息、输入框自适应高度)、useWebSocket通信Hook(指数退避重连1s→2s→4s→最多30s、token在sessionStorage持久化以支持断线恢复)。状态机管理Idle→Thinking→Speaking→Bridging的完整流转,idle动画通过JavaScript接管时间线替代浏览器原生loop,避免循环交界的帧停顿。

流式管道是系统的核心设计。LLM以流式输出token,后端按句子边界实时切段,每切出一个完整句子即提交给TTS合成语音。首段采用"跳过语义分析"的快速通道(skip_llm_semantic),优先保证低延迟;后续段落并行进行语义分析,根据分析结果从预制的avatar视频片段库中选择匹配的口型与表情视频,通过FFmpeg拼接为完整段落视频,上传至MinIO后向前端推送segment_ready事件。

前端收到事件后,AvatarView执行showMain切换------预加载目标视频,canplay后立即切换显示,先隐藏旧帧再显示新帧以避免黑闪。idle动画通过JavaScript接管时间线(timeupdate在距末尾小于0.05秒时主动seek(0)),替代浏览器原生loop机制,消除循环切换时的顿挫感。

RAG检索增强:用户消息触发后,Agent引擎先通过Embedding服务将查询向量化,在Qdrant中按角色集合映射检索相关文档片段,将Top-K结果注入LLM的system prompt作为上下文。如果Qdrant不可用,系统降级为纯LLM模式,不阻塞对话。

TTS长文本处理:对超过450字符的段落,TTS引擎按句子边界拆分后并行合成各片段,最后用FFmpeg拼接为完整音频。全局信号量限制TTS并发数,避免触发DashScope的限流(429)。

部署:Docker Compose一键拉起Qdrant、Redis、MinIO、后端服务和Nginx。Nginx负责静态资源缓存、API反向代理和WebSocket升级。配置文件通过JSON + 环境变量合并,优先级:环境变量 > config.json > 默认值。


四、成果与收获

RealTimeTalk经过多轮迭代,在以下方面取得了关键成果:

低延迟流水线:首段语音从LLM开始输出到前端开始播放,通过流式切段 + 跳过语义分析的快速通道设计,将"用户发送消息→数字人开始说话"的感知延迟控制在合理范围内,用户不再有"对方在打字"的等待感。

流畅的形象切换:双video叠加 + JavaScript接管idle循环的设计,解决了avatar在idle↔speaking切换时的黑闪、跳变和顿挫问题。Speaking态通过scale(1.7)保持与idle态的视觉大小一致,消除了缩放突变。

稳健的错误处理:全链路具备降级能力。Qdrant不可用时降级为纯LLM模式;MinIO上传失败时回退本地文件路径;TTS限流时信号量排队等待;WebSocket断连时指数退避重连。系统不会因为单个外部依赖的故障而整体不可用。

可复制的工程资产:项目通过Repowiki自动化生成了完整的中文知识库文档,覆盖架构设计、API规范、前端组件、部署运维等维度,使新人可以基于文档快速理解全貌并参与开发。

在整个构建过程中,一个日益清晰的体感是:实时数字人对话的工程难点,不在AI的能力,而在"管道的编排"。 LLM、TTS、语义分析、视频拼接,每一项单独调用都不是难题;难的是把它们串成一条低延迟、可降级、有节奏的流式管道,让用户感知到的不是一堆异步任务的拼凑,而是一次连贯的对话。此外,avatar的视觉体验打磨也是时间消耗的大头------idle循环的顿挫感、speaking切换的黑闪、状态过渡的缩放突变,这些问题在Demo阶段往往被忽略,但在真实使用中每一个都会成为用户流失的原因。修复它们的过程反复验证了一个朴素的原则:前端媒体调度的精细程度,决定了一个数字人产品是"能用"还是"好用"。


五、实践成果

RealTimeTalk 的核心技术方案已在实际项目中落地验证。基于该系统构建的智能规划平台已上线运行:

网站地址pulan.smartmoves.com.cn

该平台将实时数字人对话能力与 Agent Skill Warehouse(mcp.smartmoves.com.cn)的技能治理体系相结合,提供从需求分析到方案输出的端到端智能协作体验。