# Tennis Training Hub 网球训练管理与分析应用,提供训练计划、姿势分析、实时摄像头分析、在线视频录制与视频库管理。当前版本在媒体服务之外新增数据库驱动的后台任务系统,用于承接训练计划生成、动作纠正、多模态分析和录制归档这类高延迟任务。 ## Architecture - `client/`: React 19 + TypeScript + Tailwind CSS 4 + shadcn/ui - `server/`: Express + tRPC + Drizzle + MySQL/TiDB,负责业务 API、登录、训练数据与视频库元数据 - `media/`: Go 媒体服务,负责录制会话、分段上传、WebRTC 信令、关键片段标记与 FFmpeg 归档 - `server/worker.ts`: Node 后台 worker,负责执行重任务队列 - `docker-compose.yml`: 单机部署编排 - `deploy/nginx.te.hao.work.conf`: `te.hao.work` 的宿主机 nginx 入口配置 ## Online Recording 在线录制模块采用双链路设计: - 浏览器端 `MediaRecorder` 本地压缩并每 60 秒自动分段上传 - 浏览器端 `RTCPeerConnection` 同步建立 WebRTC 低延迟推流链路 - 客户端运动检测自动写入关键片段 marker,也支持手动标记 - 摄像头中断后自动重连,保留既有分段与会话 - Go 媒体 worker 将分段合并归档,并产出 WebM 回放;FFmpeg 可用时额外生成 MP4 - Node app worker 轮询媒体归档状态,归档完成后自动登记到视频库并向任务中心反馈结果 - 服务端媒体会话校验兼容 `/media/sessions/...` 路径,避免录制结束时因路径不一致导致 404 ## Background Tasks 统一后台任务覆盖以下路径: - `training_plan_generate` - `training_plan_adjust` - `analysis_corrections` - `pose_correction_multimodal` - `media_finalize` 前端提供全局任务中心,页面本地也会显示任务提交、执行中、完成或失败状态。训练页、分析页和录制页都可以在用户离开页面后继续完成后台任务。 另外提供独立日志页 `/logs`,用于查看后台任务历史、失败原因与通知记录。 ## Multimodal LLM - 文本类任务使用 `LLM_API_URL` / `LLM_API_KEY` / `LLM_MODEL` - 图片类任务可单独指定 `LLM_VISION_API_URL` / `LLM_VISION_API_KEY` / `LLM_VISION_MODEL` - 所有图片输入都要求可从公网访问,因此本地相对路径会通过 `APP_PUBLIC_BASE_URL` 规范化为绝对 URL - 若视觉模型链路不可用,系统会自动回退到结构化指标驱动的文本纠正,避免任务直接失败 - 系统内置“视觉标准图库”页面 `/vision-lab`,可把公网网球参考图入库并保存每次识别结果 - `ADMIN_USERNAMES` 可指定哪些用户名账号拥有 admin 视角,例如 `H1` - 用户名登录支持直接进入系统;仅首次创建新用户时需要填写 `REGISTRATION_INVITE_CODE` ## Quick Start ### Local development ```bash pnpm install cp .env.example .env pnpm dev ``` 本地开发时: - Node 应用默认运行在 `http://localhost:3000` - 若设置 `MEDIA_SERVICE_URL=http://127.0.0.1:8081`,Express 会把 `/media` 代理到 Go 服务 - Go 媒体服务可单独启动: ```bash cd media go mod tidy go run . ``` ### Checks ```bash pnpm check pnpm test pnpm test:go pnpm build pnpm test:e2e pnpm verify cd media go build ./... ``` 首次运行浏览器测试前执行: ```bash pnpm exec playwright install chromium ``` ## Production Deployment 单机部署推荐: 1. 宿主机 nginx 处理 `80/443` 和 TLS 2. `docker compose up -d --build` 启动 `app + app-worker + media + media-worker + db` 3. nginx 将 `/` 转发到宿主机 `127.0.0.1:3002 -> app:3000`,`/media/` 转发到 `127.0.0.1:8081 -> media:8081` 4. 如需绕过 nginx 直连调试,也可通过公网 4 位端口访问主站:`http://te.hao.work:8302/` 详细步骤见: - `docs/deploy.md` - `docs/media-architecture.md` - `docs/frontend-recording.md` ## Documentation Index - `docs/FEATURES.md`: 当前功能特性与能力边界 - `docs/testing.md`: 自动测试分层与运行方式 - `docs/verified-features.md`: 已验证通过的项目清单 - `docs/developer-workflow.md`: 阶段可中断的开发与本地提交流程 - `docs/deploy.md`: 部署指南 - `docs/media-architecture.md`: 媒体服务架构 - `docs/frontend-recording.md`: 前端录制与移动端适配说明 ## Environment 关键环境变量见 `.env.example`,重点包括: - `DATABASE_URL` - `JWT_SECRET` - `ADMIN_USERNAMES` - `REGISTRATION_INVITE_CODE` - `MYSQL_DATABASE` - `MYSQL_USER` - `MYSQL_PASSWORD` - `MYSQL_ROOT_PASSWORD` - `LLM_API_URL` - `LLM_API_KEY` - `LLM_MODEL` - `LLM_VISION_API_URL` - `LLM_VISION_API_KEY` - `LLM_VISION_MODEL` - `APP_PUBLIC_BASE_URL` - `LOCAL_STORAGE_DIR` - `MEDIA_SERVICE_URL` - `VITE_MEDIA_BASE_URL` LLM 烟雾测试: ```bash pnpm test:llm pnpm test:llm -- "你好,做个自我介绍" ``` ## Notes - 浏览器兼容目标以 Chrome 为主 - 录制文件优先产出 WebM,MP4 为服务端可选归档产物 - 存储策略当前为本地卷优先,适合单机 Compose 部署