Roadmap: 从离线视频生成 → 实时交互直播平台
Role: AI Full-Stack & Streaming Architecture Agent
Mission Overview
The "Talking Avatar Platform" currently works perfectly in a local macOS Docker environment using a decoupled architecture (Go API + Python Worker + RustFS + Redis).
Our next evolutionary leap is to upgrade the platform from an "Offline Asynchronous Video Generator" to a "Real-time Interactive Streaming Platform", while also migrating the compute layer to a Linux + AMD GPU environment.
Execute the following Roadmap sequentially. Do NOT move to Phase 2 before Phase 1 is fully tested.
状态图例
- ✅ 已完成并提交
- [~] 代码已就绪,待 AMD 机器实机验证
- [ ] 未开始
Phase 1: Compute Migration & AMD GPU Enablement(计算迁移)
Goal: Migrate the Python Worker from macOS (MPS/CoreML) to Ubuntu Linux with AMD GPUs using ROCm.
Tasks
- Worker Dockerfile Update (AMD ROCm) — ✅
- Official ROCm PyTorch image is now the default in
worker/Dockerfile. - Base image:
rocm/pytorch:rocm7.2.4_ubuntu24.04_py3.12_pytorch_release_2.10.0. uv sync --inexactis used to preserve the PyTorch GPU build.- 接入
docker-compose.yml(worker-rocm服务,profile: rocm,透传/dev/kfd+/dev/dri)。
- Official ROCm PyTorch image is now the default in
- ONNX Runtime Adjustments — ✅
- 已实现:
onnx_utils.build_session()自动检测ROCMExecutionProvider, 支持WAV2LIP_PROVIDER=rocm,逐节点回退 CPU。 - 已实现:
real.py默认使用Wav2LipOnnxLipSync(ONNX 后端)。
- 已实现:
- Environment Parity Check — [~]
- 在 Ubuntu ROCm 容器内验证 S3/Redis 连接逻辑(
--network=host)。 - 跑通一个测试任务,生成时间与 macOS CoreML 基准(约 10 秒)相当或更快。
- 在 Ubuntu ROCm 容器内验证 S3/Redis 连接逻辑(
Phase 2: Business Logic Completion(业务闭环)
Goal: Complete the Avatar listing feature on the Frontend and API.
Tasks
- Go API (Backend) — ✅
GET /api/avatars+GET /api/avatars/:id(轮询初始化状态);创建时voice_id/status=initializing/avatar_init队列;base 视频回写 Webhook。
- Frontend (shadcn-admin) — ✅
- Avatar Library 响应式卡片 + 状态徽标;Avatar Studio 改为纯创建页 (名称/图片/Edge-TTS 音色 + 初始化轮询);Broadcast 播报页;Live Studio。
Phase 3: Streaming Architecture Reboot(流式架构)
Goal: 引入 RTMP 流媒体网关,将 Worker 推理管线重构为 内存 → 网络持续推流,不再落盘 MP4。
Step 3.1: SRS Streaming Gateway — ✅
- ✅ 在
docker-compose.yml集成 SRS(ossrs/srs:5)容器。 - ✅ 端口:仅发布 1935 RTMP 供宿主机 Worker 推流;1985 HTTP API 与 8080 HTTP-FLV 只在内网(避免向宿主机开放调试端口)。
- ✅ 拉流经 Nginx
/live/代理到srs:8080(内网)。
Step 3.2: Streaming Pipeline Refactor(交互式问答)— ✅
- ✅ 分句处理:
POST /api/live/{id}/push按。!?!?;;/换行切句,顺序入队live_queue:{id}。 - ✅ 内存 → RTMP:
stream_worker.py常驻 ffmpeg 双管道(BGR24 帧 stdin + s16le 音频 /dev/fd/3,视频输入-re实时节流)推流rtmp://localhost:1935/live/avatar_<id>;闲置态喂静音音频 + base 动画, 说话态喂口型帧 + TTS 音频,管道全程不关闭。离线 MP4 逻辑保留。 - ✅
POST /api/live/{id}/start|push|status已落地;LLM 链路由POST /api/live/{id}/message完成(OpenAI Go SDK → DeepSeek Responsesdeepseek-v4-flash→ 回复切句入live_queue:{id};无 key 时回显原文), 已异步化:接口先 202 立即返回,LLM 生成 + 入库 + 入队在后台 goroutine 执行(30s 超时),发送不再阻塞。观众端已拆为独立 Next.js + TailwindCSS 项目(frontend/live/,:3000):/开播列表 +/rooms/:avatarId直播间(xgplayer + 服务端代理)。
Step 3.3: 7x24 Long-form Broadcast(长时直播)— [~]
- [~] 异步多线程:闲置期间 TTS 异步预取,说话切换不等待;base 动画按流缓存 (
LIVEPORTRAIT_IDLE_BASE_SECONDS控制,默认 10s)。 - [ ] 会话保持 / 断流重连 / 多流并发资源调度(未开始)。
Phase 4: 直播体验与智能升级(口型 / 性能 / 记忆 / 知识库)
Goal: 从「能用」走向「好用」:修复口型变形、消除直播卡顿,并让数字人 具备长期记忆与私有知识库(RAG),减少多轮对话降智与专业问答幻觉。
Task 4.1 口型变形修复(Lip-sync Deformation)— ✅
- ✅ 已实现双轨人脸修复引擎(
worker/ai/enhancer.py,纯 ONNX):- 直播(GFPGANEnhancer):GFPGANv1.4.onnx 只修复人脸 ROI(Bounding Box), 羽化遮罩(Feathered Mask)贴回原帧,省约 80% 计算量。
- 离线(CodeFormerEnhancer):codeformer.onnx 全脸修复,
fidelity_weight(w=0.6,ONNX 的w输入)可调。
- ✅ 模型下载:
uv run python download_models.py --models restoration→worker/models/restoration/{gfpgan,codeformer}/*.onnx(已实测跑通)。 - ✅ 管线接入:
lipsync_onnx帧级增强钩子(有 enhancer 才生效);real.py(离线)默认 codeformer(FACE_ENHANCER=off可关);直播管线不使用人脸 增强(Watchdog 需恒定 24fps),缺模型自动降级 no-op。 - ✅ 直播增强实测结论(2026-08):本机 CoreML 下 CodeFormer ≈1.4s/帧、 GFPGAN ≈2.5s/帧,直播开启会滞后 ~1 分钟,维持默认关闭;增强留待 Linux CUDA/ROCm 机器(GPU 上 GFPGAN ROI)再评估。
- ✅ 实机画质验收:离线成品对比视频已放
docs/videos/(noCodeFormer.mp4vsCodeFormer.mp4),观感提升明显;后续可在不同 形象/语速下微调roi_padding/feather_ratio/CODEFORMER_FIDELITY_WEIGHT。
Task 4.2 口型性能与推流卡顿(Latency / Streaming Stutter)— ✅
- ✅ Watchdog 架构已落地(
stream_worker.py):- 消费推流线程(Watchdog):独立线程以恒定
fps(默认 24)向 ffmpeg 写帧,读Ready_Frames_Queue;队列空时立即回退 base 动画帧 + 静音音频, 推流永不中断、播放器不转圈。 - 生产推理线程:异步 Edge-TTS → Wav2Lip 小批量(8 帧)产帧入队, 首批即切换说话;连续多句无缝拼接(产帧快于实时)。
- ffmpeg 去掉
-re,改由 Watchdog 在 Python 侧精确节流(避免 lag→EOF 断流)。
- 消费推流线程(Watchdog):独立线程以恒定
- [ ] 实机长播压测:多轮连续弹幕 + 长文本,观察推流/播放器是否持续无卡顿。
Task 4.3 长期记忆(Long-term Memory)— ✅
- ✅ 已实现:Go
llmChat每次回复前取该数字人最近 10 条房间消息 (live_messages,按 avatar_id 作为会话)注入 System Prompt (user/assistant 格式),支持多轮连续对话;窗口外旧消息直接丢弃控 Token。
Task 4.4 私有知识库(RAG)— ✅
- ✅ Part 1 + 2 + 3(已重构):知识库升级为全局共享 + N:N 绑定 —— 知识库(Collection,
knowledge_collections,全局唯一名称、不再属于某个 机器人)→ 文档(Document,knowledge_documents:text/.txt/.pdf,源文件 入 S3,Go 用ledongthuc/pdf提取 PDF 文本);机器人通过avatar_knowledge(avatar_id + collection_id 复合主键,enabled 开关) 绑定若干知识库,多个数字人可共用一个;service-rag微服务(zvec 全文 索引 + Jieba 中文分词,零模型/零下载)负责入库/v1/knowledge/ingest、 检索/v1/knowledge/search(按 avatar_id / collection_id / collection_ids 标量过滤 + BM25 Top-3)、删除/v1/knowledge/delete、 分块查看/v1/knowledge/chunks。Go 聊天端点先查该数字人enabled=true的绑定集合,再按 collection_ids 检索 Top-3 注入 System Prompt;观众只发关键词时视为「想了解该主题」主动讲解。 - ✅ 检索方案演进(已落地):原计划「RedisStack(RediSearch)做 KNN + BAAI bge-small 向量化」已由 service-rag(zvec 进程内全文索引 + 自带 Jieba 中文分词) 取代——不需要向量模型、不需要 RediSearch、零下载; Redis 已回退
redis:8.2.2-alpine,worker/rag_worker.py及其依赖 (pymupdf / sentence-transformers)已删除。 - ✅ 查询与拼接:观众提问 → service-rag 按数字人聚合 Top-3 → 作为
<Context>注入 DeepSeek System Prompt,强制只根据知识库回答,减少 带货/专业问答幻觉;管理端可在线检索测试并查看文档分块。
近期已完成(Roadmap 之外落地)
- ✅ 知识库管理后台:入库页(
/knowledge,文本/.txt/.pdf)+ 列表页 (/knowledge知识库列表 +/knowledge/$id文档详情:创建/重命名/删除 知识库、文档增删、按知识库在线 Top-3 检索测试)。 - ✅ 知识库全局化:知识库从「属于单个数字人」改为「全局共享集合」, 数字人编辑页右侧「知识库」面板勾选绑定(即时保存);已入库旧数据自动 迁移为绑定关系(
migrateGlobalKnowledge),检索按绑定集合隔离。 - ✅ 聊天日志页:
/chat-logs按数字人/用户 ID/日期/关键字检索 + 分页 (page/pageSize+ total);机器人回复持久化rag_hit/rag_sources, 页面标注「命中知识库」并可展开查看命中的知识片段。 - ✅ 客户端用户中心:
/account身份卡(游客/账号)、注册/登录/退出、 「我的消息」(GET /api/chat/history?userId=);导航身份胶囊可点击进入; 首页美化(Hero CTA、卡片悬停进入直播间、页脚账号中心入口)。 - ✅ 直播链路稳定化:音频切片先于视频帧写入(防 AAC 欠载)、ffmpeg 保留
-re(Watchdog 兜底填帧)、Redis 断连 1s 静默退避。 - ✅ RAG 迁移到 service-rag:compose 新增
service-rag(zvec FTS + Jieba,volumerag-zvec-data),EMBED_SERVER_URL默认http://service-rag:8001;Redis 回退redis:8.2.2-alpine(不再需要 RediSearch),worker/rag_worker.py与脚本中的 rag_worker 已删除。 - ✅ TTS 微服务(service-tts):async
edge_tts.Communicate→ ffmpeg 转 16kHz/16-bit/mono PCM WAV → 上传 S3(RustFS,S3 配置走环境变量)→ 只返回 S3 key + 元数据,finally清理临时文件;compose 内网 :8002,不发布宿主端口。 - ✅ 端口收敛:宿主机不调试,SRS 只发布 1935(RTMP 推流),1985/8081 收回内网;
api/service-rag/service-tts均不发布端口;对外仅 3000/8080/1935/6379/9000。 - ✅ TTS 试听接口重构(后效优化):
POST /api/tts/preview音色试听已改为 直接 HTTP 调用service-tts微服务的/v1/tts/preview(试听为一次性临时 数据,直接返回字节、不走 S3);backend/Dockerfile已移除python3/edge-tts依赖,后端镜像不再捆绑 Python。 - ✅ 存储与任务队列演进:MinIO → RustFS(SNSD 单盘模式);S3 环境变量 双命名兼容(
S3_*主约定 +RUSTFS_ENDPOINT_URL/AWS_ACCESS_KEY_ID/ AWS_SECRET_ACCESS_KEY/S3_BUCKET_NAME别名,path-style);worker 支持{type:"render",text,tts_s3_key,base_video_s3_key}任务(base 视频 LRU 缓存、TTS wav 用完即删),旧 taskId 格式向后兼容。 - ✅ 直播会话恢复修复:api-scheduler 补
GET /api/live,stream_worker 重启后按 DB 恢复直播会话。 - ✅ 前端容器加固:frontend-admin nginx 设 Asia/Shanghai 时区; frontend-live 改为非 root(node)运行(chown 在 COPY 之后,
/app可写)。 - ✅ 场景(数字人 → 场景 → 视频):
scenes+scene_videos两张表; 场景有标题/描述/封面,视频有描述;创建数字人的 base 视频成为默认场景的 默认视频(直播/播报兜底,默认场景/默认视频不可删)。接口:GET/POST /api/avatars/:id/scenes、PUT/DELETE /api/scenes/:id、POST /api/scenes/:id/videos、DELETE /api/scenes/:id/videos/:vid; 任务创建支持sceneId + videoId;人物设定收进avatars.personaJSON,base_video_s3_key与旧avatar_videos彻底移除(启动时一次性迁移)。 - ✅ 任务进度分阶段 + TTS 复用:worker 按
tts/lipsync/mux上报 stage、 每 1% 上报 progress(前端进度条 + 阶段标签);TTS 首次合成后缓存到 S3 (tts/tasks/{id}.wav),重试直接复用不再合成;删除任务时一并清理。 - ✅ 直播默认推流视频(场景 + 切换):
live_settings新增idleSceneId/idleSwitchMode(interval|random)/idleSwitchSeconds,Live Studio 移除「发送文字」、新增「默认推流视频」卡片(选场景 + 定时 N 秒/随机切换); start 控制消息与GET /api/live携带idleVideos(所选场景全部视频 S3 Key); worker 下载全部闲置视频(同分辨率),闲置态定时顺序或随机(5-30s)切换; 说话口型基于当前正在显示的那段场景视频(_slice_current_idle),说完从 该视频衔接处继续,不再固定默认视频。 - ✅ Agentic 场景/动作视频(1v1):DeepSeek System Prompt 注入当前场景全部 动作视频(S3 Key + 描述),LLM 可在句首输出
<action:S3_KEY>;后端parseActionTag剥离标签(不入库/不显示/不说出)并把 key 作为该句base_video_s3_key(无标签回退默认视频);PUT /api/live/session/:id/scene切换活跃场景(更新live_sessions.scene_id+live_settings.idleSceneId, 推switch_scene控制消息带video_pool);worker 用_idle_lock原子替换 闲置视频池(不打断 Watchdog),动作句按需 S3 加载(LRU 缓存);观众端SceneSwitcher胶囊条 + 切换反馈。 - ✅ Telegram Mini App 登录 + Ngrok 隧道:
POST /api/auth/telegram(api-telegram) 校验initData(HMAC-SHA-256 + 24h 时效)并 upsertlive_users/telegram_users(按telegram_id,非游客,HttpOnlytg_uidcookie);frontend/telegram用@twa-dev/sdk取WebApp.initData调该接口(VITE_API_ORIGIN可指向 ngrok api-gateway);根ngrok.yml双隧道 + composengrok服务,TG_BOT_TOKEN/NGROK_AUTHTOKEN/VITE_API_ORIGIN见.env.example。 - ✅ Telegram Webhook 自动发现与注册:api-telegram 启动时后台 goroutine 轮询
NGROK_API_URL(http://ngrok:4040/api/tunnels,2s × 10 重试)取api-gateway公网地址 →setWebhook注册/api/telegram/webhook(占位 200 OK);单测覆盖发现/未就绪/注册/重试四类场景。 - ✅ TG 注册环境变量优先:
TG_WEBHOOK_URL/TG_MINIAPP_URL优先于 ngrok (生产固定域名);缺失时按隧道发现(api-gateway→webhook、tg-app→菜单按钮), 两者都有则跳过 ngrok;setChatMenuButton注册 Mini App 入口,来源日志清晰。
Strict Rules for Execution
- 先给出 Phase 1 所需的精确命令与代码调整,测试通过后再进入下一阶段。
- 不重写整个系统;模块化注入改动,保持现有 API + DB + S3 + Nginx 架构不变。
- Phase 3 优先稳定性而非极致低延迟:先保证分句与 FFmpeg 管道不崩溃,再优化线程。