Checkpoint: v4.0 media service, compose deploy, and verified docs

这个提交包含在:
cryptocommuniums-afk
2026-03-14 21:45:31 +08:00
父节点 27083d5af9
当前提交 d5431aee0e
修改 41 个文件,包含 4056 行新增883 行删除

258
README.md
查看文件

@@ -1,186 +1,102 @@
# Tennis Training Hub - AI网球训练助手
# Tennis Training Hub
一个基于AI的在家网球训练平台,通过MediaPipe姿势识别技术帮助用户在只有球拍的条件下进行科学训练,自动分析挥拍姿势并生成个性化训练计划
AI 网球训练助手,提供训练计划、姿势分析、实时摄像头分析、在线视频录制与视频库管理。当前版本新增独立 Go 媒体服务,用于处理在线录制、分段上传、实时推流信令和归档回放
## 功能概览
## Architecture
| 功能模块 | 描述 | 技术实现 |
|---------|------|---------|
| 用户名登录 | 无需注册,输入用户名即可使用 | tRPC + JWT Session |
| 训练计划生成 | 根据用户水平(初/中/高级AI生成训练计划 | LLM结构化输出 |
| 视频上传分析 | 上传训练视频进行姿势识别 | MediaPipe Pose + S3 |
| 实时摄像头分析 | 手机/电脑摄像头实时捕捉分析 | MediaPipe实时推理 |
| 在线录制 | 稳定压缩流录制、断线重连、自动剪辑 | MediaRecorder API |
| 姿势矫正建议 | AI根据分析结果生成矫正方案 | LLM + 姿势数据 |
| NTRP自动评分 | 基于USTA标准的五维度加权评分 | 自动算法 |
| 训练计划自动调整 | 根据分析结果智能调整后续计划 | LLM + 历史数据 |
| 每日打卡 | 连续打卡追踪、训练时长记录 | 日期计算 + 数据库 |
| 成就徽章 | 24种成就徽章激励系统 | 自动检测 + 授予 |
| 社区排行榜 | NTRP评分、训练时长、击球数排名 | 数据库排序查询 |
| 训练进度追踪 | 可视化展示训练历史和改进趋势 | Recharts图表 |
| 视频库管理 | 保存管理所有训练视频及分析结果 | S3 + 数据库 |
| 移动端适配 | 全面响应式设计,手机摄像头优化 | Tailwind响应式 |
- `client/`: React 19 + TypeScript + Tailwind CSS 4 + shadcn/ui
- `server/`: Express + tRPC + Drizzle + MySQL/TiDB,负责业务 API、登录、训练数据与视频库元数据
- `media/`: Go 媒体服务,负责录制会话、分段上传、WebRTC 信令、关键片段标记与 FFmpeg 归档
- `docker-compose.yml`: 单机部署编排
- `deploy/nginx.te.hao.work.conf`: `te.hao.work` 的宿主机 nginx 入口配置
## 技术栈
## Online Recording
**前端:**
- React 19 + TypeScript
- Tailwind CSS 4 + shadcn/ui
- MediaPipe Pose浏览器端姿势识别
- Recharts数据可视化
- Framer Motion动画效果
- wouter路由
在线录制模块采用双链路设计:
**后端:**
- Express 4 + tRPC 11
- Drizzle ORM + MySQL/TiDB
- S3文件存储
- LLM集成训练计划生成、姿势矫正建议
- 浏览器端 `MediaRecorder` 本地压缩并每 60 秒自动分段上传
- 浏览器端 `RTCPeerConnection` 同步建立 WebRTC 低延迟推流链路
- 客户端运动检测自动写入关键片段 marker,也支持手动标记
- 摄像头中断后自动重连,保留既有分段与会话
- 服务端 worker 将分段合并归档,并产出 WebM 回放;FFmpeg 可用时额外生成 MP4
## 项目结构
## Quick Start
```
tennis-training-hub/
├── client/
│ ├── src/
│ │ ├── pages/
│ │ │ ├── Home.tsx # 落地页
│ │ │ ├── Login.tsx # 用户名登录
│ │ │ ├── Dashboard.tsx # 仪表盘
│ │ │ ├── Training.tsx # 训练计划
│ │ │ ├── Analysis.tsx # 视频分析MediaPipe
│ │ │ ├── LiveCamera.tsx # 实时摄像头分析
│ │ │ ├── Recorder.tsx # 在线录制
│ │ │ ├── Videos.tsx # 视频库
│ │ │ ├── Progress.tsx # 训练进度
│ │ │ ├── Rating.tsx # NTRP评分详情
│ │ │ ├── Leaderboard.tsx # 社区排行榜
│ │ │ └── Checkin.tsx # 每日打卡+徽章
│ │ ├── components/
│ │ │ └── DashboardLayout.tsx # 侧边栏导航布局
│ │ ├── App.tsx # 路由配置
│ │ └── index.css # 主题样式
│ └── index.html
├── server/
│ ├── routers.ts # tRPC路由定义
│ ├── db.ts # 数据库查询助手
│ ├── storage.ts # S3存储助手
│ ├── features.test.ts # 功能测试47个
│ └── _core/ # 框架核心(勿修改)
├── drizzle/
│ └── schema.ts # 数据库表结构
└── shared/
└── const.ts # 共享常量
```
## 数据库设计
### 核心表
| 表名 | 用途 | 关键字段 |
|------|------|---------|
| `users` | 用户信息 | openId, name, skillLevel, ntrpRating, totalSessions, currentStreak |
| `username_accounts` | 用户名登录映射 | username, userId |
| `training_plans` | AI训练计划 | exercises(JSON), skillLevel, durationDays, version |
| `training_videos` | 训练视频 | fileKey, url, format, analysisStatus |
| `pose_analyses` | 姿势分析结果 | overallScore, shotCount, avgSwingSpeed, strokeConsistency |
| `training_records` | 训练记录 | exerciseName, durationMinutes, completed, poseScore |
| `rating_history` | NTRP评分历史 | rating, dimensionScores(JSON), analysisId |
| `daily_checkins` | 每日打卡 | checkinDate, streakCount, minutesTrained |
| `user_badges` | 成就徽章 | badgeKey, earnedAt |
## NTRP自动评分系统
评分基于USTA美国网球协会的NTRP标准,范围1.0-5.0,采用五维度加权计算:
| 维度 | 权重 | 说明 |
|------|------|------|
| 姿势正确性 | 30% | 基于MediaPipe关键点角度分析 |
| 击球一致性 | 25% | 多次挥拍动作的稳定性 |
| 脚步移动 | 20% | 身体重心移动和步法评估 |
| 动作流畅性 | 15% | 挥拍动作的连贯性和自然度 |
| 力量表现 | 10% | 基于挥拍速度估算 |
**评分映射规则:**
- 0-20分 → NTRP 1.0-1.5(初学者)
- 20-40分 → NTRP 1.5-2.5(初级)
- 40-60分 → NTRP 2.5-3.5(中级)
- 60-80分 → NTRP 3.5-4.5(中高级)
- 80-100分 → NTRP 4.5-5.0(高级)
评分会根据最近20次视频分析结果自动更新,近期分析权重更高。
## 成就徽章系统
共24种成就徽章,分为6个类别
| 类别 | 徽章数 | 示例 |
|------|--------|------|
| 里程碑 | 1 | 初来乍到(首次登录) |
| 训练 | 6 | 初试身手、十次训练、百次训练、训练时长里程碑 |
| 连续打卡 | 4 | 三日坚持、一周达人、两周勇士、月度冠军 |
| 视频 | 3 | 影像记录、视频达人、视频大师 |
| 分析 | 4 | AI教练、优秀姿势、完美姿势、击球里程碑 |
| 评分 | 3 | NTRP 2.0/3.0/4.0 |
## 在线录制功能
在线录制模块提供专业级录制体验:
- **稳定压缩流**使用MediaRecorder API,自适应码率1-2.5Mbps,支持webm/mp4格式
- **断线自动重连**:摄像头意外断开时自动检测并重新连接,保存已录制片段
- **自动剪辑**:基于运动检测自动标记关键时刻,支持手动设置剪辑点
- **分段录制**每60秒自动分段,防止数据丢失
- **手机摄像头优化**:支持前后摄像头切换,自适应分辨率
## 移动端适配
- 安全区域适配iPhone X+刘海屏)
- 触摸友好的44px最小点击区域
- 横屏视频优化
- 防误触下拉刷新(录制/分析模式)
- 响应式侧边栏导航
- 移动端底部导航栏
## 测试
项目包含47个vitest测试用例,覆盖所有核心后端功能
### Local development
```bash
pnpm test
```
测试覆盖范围:
- 认证系统(登录、登出、用户名验证)
- 用户资料管理
- 训练计划生成(输入验证)
- 视频上传和管理
- 姿势分析保存和查询
- 训练记录创建和完成
- NTRP评分系统
- 每日打卡系统
- 成就徽章系统
- 社区排行榜
## 开发
```bash
# 安装依赖
pnpm install
# 启动开发服务器
cp .env.example .env
pnpm dev
# 运行测试
pnpm test
# 类型检查
pnpm check
# 构建生产版本
pnpm build
```
## 许可证
本地开发时:
MIT License
- 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 + media + worker`
3. nginx 将 `/` 转发到 `app:3000``/media/` 转发到 `media:8081`
详细步骤见:
- `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`
- `MEDIA_SERVICE_URL`
- `VITE_MEDIA_BASE_URL`
## Notes
- 浏览器兼容目标以 Chrome 为主
- 录制文件优先产出 WebM,MP4 为服务端可选归档产物
- 存储策略当前为本地卷优先,适合单机 Compose 部署