用普通摄像头或本地视频,获得专业级 MJ 舞步评分。
依托 MediaPipe BlazePose 实时追踪 33 个人体关键点,逐关节提取角度,自动对比内置的 MJ 标准骨骼参考,每一帧动作立即量化反馈。无需传感器,无需后端,打开浏览器即用。
| Feature | Detail | |
|---|---|---|
| 🦴 | Virtual Reference Dancer | 8 signature MJ moves encoded as canonical 33-landmark keyframe sequences, interpolated to BPM and rendered as a live AR skeleton |
| 📷 | Live Camera Mode | MediaPipe BlazePose at 60 fps, 33 joints, fully on-device — no data leaves the browser |
| 🎬 | Video Analysis Mode | Upload any MP4 / MOV / WebM recording of yourself; pose detection and scoring run frame-by-frame |
| 📐 | Joint-Weighted Scoring | Each move weights joints differently — Smooth Criminal grades torso lean hardest; Robot Lock grades elbow angles |
| 📊 | Real-time Analytics | Per-joint radar chart, smoothed S→D grade gauge, combo counter, coach feedback |
| YouTube Reference Panel | Pin any YouTube live performance to any move; persists in localStorage |
| Move | 中文名 | Era | Difficulty |
|---|---|---|---|
| The Moonwalk | 月球漫步 | Motown 25 · 1983 | Signature |
| Anti-Gravity Lean | 反重力倾斜 | Smooth Criminal · 1988 | Master |
| Toe Stand | 足尖站立 | Heal The World Tour · 1992 | Intermediate |
| Pelvic Snap | 招牌动作 | Bad Tour · 1987 | Signature |
| The Spin | 招牌旋转 | Dangerous Tour · 1992 | Master |
| Side Slide | 侧滑 | This Is It · 2009 | Beginner |
| Sidewalk | 侧步 | Bad Tour · 1987 | Intermediate |
| Robot Lock | 机器人锁定 | Dancing Machine · 1974 | Beginner |
git clone https://github.com/MindDock/mj-dance-analyzer.git
cd mj-dance-analyzer
npm install
npm run devOpen http://localhost:5173 — no API keys, no backend, no sensor hardware required.
┌─────────────────────────────────────────────────────────────────┐
│ Browser │
│ │
│ ┌─────────────────┐ ┌──────────────────────────────────┐ │
│ │ Reference Dancer│ │ Your Input │ │
│ │ │ │ ┌───────────┐ ┌─────────────┐ │ │
│ │ Canonical KFs │ │ │ Webcam │ │ Video file │ │ │
│ │ BPM-animated │ │ │ (mirrored)│ │ (MP4/MOV…) │ │ │
│ │ AR skeleton │ │ └─────┬─────┘ └──────┬──────┘ │ │
│ └────────┬────────┘ │ └────────┬───────┘ │ │
│ │ │ │ │ │
│ extractAngles() │ MediaPipe BlazePose @ 60fps │ │
│ (reference) │ extractAngles() (user) │ │
│ │ │ │ │ │
│ └───────────────┼────── scoreFrame() ───────────────┘ │
│ │ joint-weighted diff │
│ │ → overall 0-100 · S/A/B/C/D │
│ │ → per-joint radar │
│ └──────────────────────────────────────┘
└─────────────────────────────────────────────────────────────────┘
Each joint has a tolerance window (degrees). Per-joint score:
score = max(0, 100 × (1 - |ref_angle - user_angle| / (tolerance × 2.2)))
Overall score is a weighted average — focus joints for the current move carry higher weight, defined per move in src/data/mjMoves.ts.
src/
├── data/
│ ├── keyframes.ts # Canonical 33-landmark keyframe sequences (8 moves)
│ └── mjMoves.ts # Move metadata: BPM, difficulty, breakdown, focus weights
├── lib/
│ ├── poseMath.ts # Angle extraction, interpolation, scoring, smoothing
│ ├── poseTypes.ts # Pose33, Landmark, AngleMap, JointKey, Keyframe
│ ├── skeleton.ts # Canvas: bone glow, joint circles, angle annotations
│ ├── mediapipeLoader.ts # Lazy CDN loader (no bundled WASM)
│ └── youtube.ts # YouTube URL parser + localStorage persistence
├── components/
│ ├── ReferenceDancer.tsx # BPM-animated canonical skeleton canvas
│ ├── LivePoseCanvas.tsx # Webcam/video → MediaPipe → skeleton overlay
│ ├── ScoreGauge.tsx # Animated arc gauge with grade letter
│ ├── JointRadar.tsx # SVG spider chart of per-joint accuracy
│ ├── YouTubeFrame.tsx # YouTube embed with pinnable videoId
│ ├── MoveCard.tsx # Library grid card with live dancer preview
│ └── Header.tsx # Sticky nav
└── pages/
├── Landing.tsx # Hero + feature overview
├── Library.tsx # Filterable move catalog grid
├── MoveDetail.tsx # Demo, breakdown steps, angles, YouTube reference
└── Studio.tsx # Live training: reference + camera/video + scoring
- Framework — React 19, TypeScript 6, Vite 8
- Pose detection — MediaPipe BlazePose (CDN, WASM on-device)
- Fonts — Fraunces (display) · Inter (body) · JetBrains Mono (data)
- No UI framework — pure CSS custom properties + canvas
All pose tracking runs entirely in the browser. No video frames, landmarks, or scoring data are sent to any server.
External requests (on demand only):
- Google Fonts — typography
- jsDelivr CDN — MediaPipe WASM model files (loaded once, cached by browser)
- YouTube — only if you pin a performance video
MIT © MindDock