# track-service **Repository Path**: Wilyu45/track-service ## Basic Information - **Project Name**: track-service - **Description**: 跟踪服务 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-22 - **Last Updated**: 2026-10-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # PoseTrack — RTMW 全身姿态推理 + 分层动作理解服务 UE5 骨骼驱动场景的模型服务端:客户端上传摄像头视频帧,服务端用 **RTMW** 输出 **133 个全身关键点**(身体17 + 双脚6 + 面部68 + 双手42),实时回传 JSON。 v2 新增**分层动作理解与生成**:姿态估计和动作生成负责"逐帧骨骼", LLM 只负责"语义理解和决策",不直接处理逐帧坐标。 v2.2 引入**模型层**:时序动作识别(自训 ST-GCN-lite,与规则识别双源融合)+ 文本生成动作(MotionGPT-base,指令路由 + 程序化库回退)。 ``` 快回路(逐帧, 30~60FPS): UE5/浏览器客户端 ──JPEG(WebSocket)──▶ YOLOX检测 ─▶ RTMW姿态 ──133点JSON──▶ 客户端渲染 │ ┌── ActionRecognizer(滑动窗口规则, source=rule) └── TemporalRecognizer(ST-GCN-lite, source=model) └──action 事件──▶ 客户端 慢回路(低频, ~1s 粒度): action事件 / 用户chat文本 ─▶ Planner(LLM, mock/api可插拔) ─▶ 动作指令 ├─ generate 指令 ─▶ MotionGPT-base 文本→逐帧骨骼 (失败回退程序化库) └─ 其他指令 ─▶ MotionLibrary 程序化生成 └────── motion 流(分块) ──▶ 客户端播放 ``` ## 硬件与环境 - RTX 4060 8GB / CUDA 12.x 运行库(pip 自动装)/ Python 3.10 - 模型: RTMW-dw-x-l 256x192(balanced 档,openmmlab 官方 ONNX,首次启动自动下载缓存) ## 快速开始 ```bash # 1. 创建环境 python3 -m venv .venv .venv/bin/pip install -r requirements.txt .venv/bin/pip install nvidia-cuda-runtime-cu12 nvidia-cudnn-cu12 \ nvidia-cublas-cu12 nvidia-cufft-cu12 nvidia-cusolver-cu12 nvidia-cusparse-cu12 # 2. 预下载模型(可选, 首次推理也会自动下载) .venv/bin/python scripts/download_models.py balanced # 3. 启动服务(run_server.sh 自动设置 CUDA 库路径) ./run_server.sh # 默认端口 8765, 可传参: ./run_server.sh 9000 # 4. 测试 # 浏览器打开 http://:8765/ 使用摄像头实时预览 # 或用 Python 测试客户端: .venv/bin/pip install opencv-python websockets .venv/bin/python clients/test_client.py --camera 0 --show .venv/bin/python clients/test_client.py --image test.jpg --loop 200 ``` ## 配置(config.yaml,可用环境变量 PT_节__键 覆盖) | 配置 | 默认 | 说明 | |---|---|---| | engine.mode | balanced | performance=RTMW-x 384x288 精度优先 / balanced=RTMW-x 256x192 推荐 / lightweight=RTMW-l-m 最快 | | engine.backend | onnxruntime | tensorrt=尝试 TensorRT EP(需安装 TensorRT 库,失败自动回退 CUDA EP)| | engine.det_interval | 1 | 每 N 帧检测一次人体,中间帧复用 bbox。单人场景 2~5 大幅提速 | | service.smooth_alpha | 0.6 | 关键点 EMA 平滑,0 关闭 | | service.drop_stale_frames | true | 最新帧优先,防延迟累积 | | server.max_concurrent_clients | 4 | 并发上限,GPU 推理全局串行队列 | | action.enabled | true | v2 快回路动作识别(规则几何+滑动窗口,零额外显存)| | action.window_sec / min_duration / cooldown | 1.2 / 0.3 / 1.0 | 识别窗口 / 防抖时长 / 触发冷却 | | action.temporal.* | enabled=true | v2.2 时序识别模型(interval=0.5s 评估限频 / threshold=0.7 / cooldown=1.0 / device=auto)| | action.gen.* | enabled=true | v2.2 MotionGPT 生成后端(max_duration=4s / lazy=true 懒加载 / device=auto)| | llm.enabled / interval | true / 1.0 | v2 慢回路开关与轮询间隔(秒) | | llm.mode | mock | mock=内置规则映射(零依赖);api=OpenAI 兼容 /chat/completions(配 base_url/api_key/model)| ## 性能(RTX 4060 实测,balanced 档 RTMW-dw-x-l 256x192 + YOLOX-m) 引擎推理(图片直连基准,不含传输): | 场景 | 耗时 | 帧率 | |---|---|---| | 纯姿态(复用bbox) | 9.0 ms | 111 FPS | | 检测+姿态(det_interval=1) | 39 ms | 25.6 FPS | 端到端(客户端→WS→推理→回传,含 JPEG 编解码): | 场景 | RTT | 服务端处理 | 等效帧率 | |---|---|---|---| | 1200x1800原图, det=1 | 57 ms | 49 ms | 17.5 FPS | | 1200x1800原图, det=3 | 33 ms | 25 ms | 36.8 FPS | | 1200x1800原图, det=5 | 27 ms | 20 ms | 41.5 FPS | | 720p, det=3 | 27 ms | 23 ms | ~37 FPS | | 720p, det=3, 双客户端并发 | 46 ms(每端) | 42 ms | 各 >20 FPS | 调优手段叠加顺序(收益从大到小):客户端降采样到 720p → det_interval 2~5 → mode 切 lightweight → TensorRT EP(`pip install tensorrt nvidia-cuda-nvrtc-cu12` 后 `PT_ENGINE__BACKEND=tensorrt`,失败自动回退 CUDA EP)。 ## v2 分层动作理解与生成 设计原则:**LLM 不直接吃逐帧骨骼坐标、不吐逐帧坐标**(30FPS × 133点 ≈ 1.2万数值/秒, 上下文爆炸且 LLM 不擅长精确数值回归)。LLM 只在慢回路处理几十个语义 token。 | 回路 | 模块 | 位置 | 延迟 | |---|---|---|---| | 快 | ActionRecognizer 规则几何+滑动窗口 | server/action/recognizer.py | 逐帧,<1ms CPU | | 快 | MotionLibrary 程序化动作生成 | server/action/motion.py | <1ms CPU | | 慢 | Planner 语义理解/决策 (LLM) | server/action/llm.py | mock <1ms;api 200ms~2s | - 可识别动作: `wave / raise_hand / jump / squat / clap / t_pose / lean / idle` - 可生成动作: `wave / bow / jump / clap / nod / idle`,style: `default / happy / calm / excited` - LLM 接入: config.yaml `llm.mode: api` + `base_url/api_key/model`(OpenAI 兼容), 返回 `{"reply", "actions":[{"action","duration","style"}]}`,解析失败自动回退 mock; 联调自测: `.venv/bin/python scripts/llm_selftest.py --mode api --base-url ... --api-key ... --model ...` - 8GB 显存安全:v2 零新增 GPU 模型;LLM 建议走云端 API 而非本地部署 - 浏览器预览页含 **motion 流回放**(分块缓冲 + 30fps 插值 + 平滑渲染),演示客户端 "渲染/插值/平滑/播放" 环节;UE5 侧示例见 clients/ue5/README.md 第 7 节 - 测试: `.venv/bin/python tests/test_action.py`(合成序列单测,全链路无 GPU 依赖) ## v2.2 模型层:时序识别 + 文本生成动作 ### 时序动作识别(ST-GCN-lite,自训练) 滑动窗口骨骼序列 `(T=32, V=17, 3)` → 髋部居中/躯干长归一化 → 3 分区图卷积 (self/neighbor/distant) + 时序卷积 → 9 类 softmax(8 动作 + unknown)。 - 与规则识别**双源融合**:事件带 `source: "rule" | "model"`,同动作冷却窗口内 去重只发一次;模型缺权重/torch 缺失时自动停用,不影响规则识别 - 模型评估限频 0.5s(不挤占推理线程),streak≥2 防抖 - 训练数据:MotionLibrary 渲染 + 程序化姿态合成,含噪声/时间扭曲/遮挡/ 旋转增强;20 epochs 约 1 分钟,val_acc=1.0(合成域) - 重新训练: `.venv/bin/python scripts/train_temporal.py`(输出 weights/temporal_gcn.pt) ### 文本生成动作(MotionGPT-base,官方预训练) Planner 可输出 `{"action": "generate", "text": "<英文动作描述>", "duration": 秒}` 指令 → MotionGPT(T5-base + VQ-VAE,HumanML3D 263 维)生成 SMPL22 关节序列 → 映射 body17 → bbox 锚定为 133 点帧流 → 复用 motion 分块下发。生成失败或后端 未部署时自动回退程序化动作库(nod),服务不中断。 - 部署依赖(缺任一则 gen 停用,日志提示): - `weights/motiongpt_s3_h3d.tar` — 官方 checkpoint(HF 镜像 motion-gpt/MotionGPT) - `weights/mgpt_deps/flan-t5-base` — T5 分词器+底模(HF 镜像,含 spiece.model) - `weights/mgpt_deps/meta/{mean,std}.npy` — HumanML3D 263 维统计 - `third_party/MotionGPT` — 官方代码库(sys.path 注入,不 pip install) - `pip install torch spiece`(torch 装本机 CUDA 版) - 显存:懒加载首次 generate 才进显存(~1GB,与 RTMW 共存 8GB),加载 4.4s, 单次生成 ~1.5s(75 帧);`lazy: false` 可改为启动即加载 - 提示词模板:Instruct checkpoint 需要指令式输入(如 "Generate a motion that captures the feeling of ..."),直接生成会退化;已内置处理 - 自测: `.venv/bin/python scripts/gen_selftest.py`(加载/推理/坐标映射/锚定断言) ### 验证结果(RTX 4060) - ST-GCN-lite 直推 acc 18/18,流式 wave 事件 source=model - MotionGPT:walk 60 帧 / wave 45 帧,躯干比 0.32~0.34,bbox 锚定不越界, 二次生成 0.7s - E2E:chat "一起跳舞吧" → generate 指令 → 75 帧 → 8 个 motion 块回传; 主链路无回归(det=3 下 ~56 FPS) ## 瓶颈说明 GPU 推理(检测+姿态)在 4060 上约 **10–40ms/帧**(取决于档位),不是瓶颈。 端到端延迟主要来自:客户端编码 + 网络传输 + 服务端 JPEG 解码。 因此客户端降采样(720p/480p)比服务端任何优化收益都大。 ## 目录结构 ``` config.yaml 服务配置 run_server.sh 启动脚本(CUDA库路径注入) server/ main.py FastAPI + WebSocket 服务, 最新帧优先调度 + v2 回路编排 protocol.py 协议常量/帧头解析/133关键点索引 pose/engine.py 推理引擎(检测+RTMW, TensorRT EP 预留) action/recognizer.py v2 快回路: 滑动窗口规则动作识别 action/temporal.py v2.2 快回路: ST-GCN-lite 时序识别(双源融合) action/llm.py v2 慢回路: Planner(mock/api 双模式) action/motion.py v2 动作库: 指令 -> 逐帧骨骼 action/gen_motion.py v2.2 生成后端: MotionGPT 文本->逐帧骨骼(+回退) webrtc.py v2.1 WebRTC 收流(aiortc 信令+视频轨解码) static/preview.html 浏览器测试客户端(含 chat 输入 + WebRTC 推流开关) clients/ test_client.py Python 测试客户端(摄像头/图片基准 + v2 消息打印) ue5/README.md UE5 接入文档 + C++ 示例 + WebRTC 推流说明 tests/test_action.py v2 识别/规划/生成单测 scripts/download_models.py 模型预下载 scripts/train_temporal.py v2.2 ST-GCN-lite 训练(合成数据) scripts/llm_selftest.py v2 LLM(mock/api) 联调自测 scripts/gen_selftest.py v2.2 MotionGPT 生成链路自测 scripts/rtc_selftest.py v2.1 WebRTC 收流链路自测 ``` ## WebRTC 视频收流(v2.1 已支持) 客户端可改用 WebRTC 推流替代 JPEG 二进制帧:服务端 aiortc + PyAV 解码 H.264/VP8 后进入**同一条推理管线**,`pose`/`action`/`llm`/`motion` 消息仍走 WebSocket, 客户端解析代码不变。 ``` 信令(WebSocket 文本): → {"type":"rtc_offer","sdp":...} ← {"type":"rtc_answer","sdp":...} # 候选内联, 免 trickle 媒体(RTP): 客户端视频轨 ──H.264/VP8──▶ PyAV 软解 ─▶ inbox(最新帧优先) ``` - 依赖: `pip install aiortc`(已加入 requirements.txt;未安装时自动回退纯 WS 模式) - 配置: `rtc.ice_servers: []` 默认局域网直连;跨 NAT 再加 STUN - E2E 自测: `.venv/bin/python scripts/rtc_selftest.py`(aiortc 合成推流→pose 回传断言) - 浏览器预览页勾选 "WebRTC 推流" 即可切换传输方式 - UE5 侧: Pixel Streaming WebRTC 栈 / libdatachannel 插件,见 clients/ue5/README.md 第 9 节 - 选型建议: 局域网 JPEG(~27ms RTT)已够实时;WebRTC 收益在弱网/WAN(码率自适应、 抗丢包)与免客户端编码 CPU ## 已知限制 - 多人同框时只跟踪置信度最高的一人(单人说需求) - TensorRT EP 未安装时静默回退 CUDA EP(日志有提示) - `latency_ms` 依赖客户端与服务端时钟对齐,跨机器建议用客户端 frame_id RTT 对账