init: animation pipeline hub — Mac↔PC bridge for converting and implementing animations

Skills (.claude/skills/): animation-creation, iclone-video-mocap,
pose-estimation (MediaPipe models via LFS), retarget-animations (deprecated).
Tools: cc/mixamo/kevin/mocap retargeters + composite baker.
Plans: animation-gen-pipeline + skills-adoption.
exchange/: incoming-fbx, converted-glb, reference-video (LFS for fbx/glb/mp4).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 10:29:17 -07:00
commit 31ba2911df
28 changed files with 3091 additions and 0 deletions
+114
View File
@@ -0,0 +1,114 @@
# Animation Gen Pipeline — Video → Recreated Dance
**Goal:** give an agent a video of people dancing; the agent breaks the choreography
down and recreates it in-game as a dance JSON, using Kevin Iglesias (KI) clips, UAL
clips, composites, and Mixamo retargets — then verifies its own recreation against the
source and iterates.
**Honest framing:** this produces a *cover version*, not motion capture. Continuous
human motion gets quantized into a discrete vocabulary of clips + composites. For game
choreography (kapa haka teams, dance floor content) that is the desired output.
## Verified infrastructure (all exists, all tested 2026-07-13)
| Piece | Where | Status |
|---|---|---|
| Dance runtime + hot-reload JSON | `src/Testing/Dance/`, `assets/dances/*.json` | SHIPPED — test bed plays dances, reloads in ~0.5s |
| Composite baking (upper/lower masks) | `CompositeClipBaker.cs` | SHIPPED |
| BPM beat clock + quantized transitions | `BeatClock.cs`, `bpm` in dance JSON | SHIPPED |
| Viewport → mp4 recording | `VideoRecorder.cs``~/Downloads/dance_*.mp4` | SHIPPED |
| Mixamo FBX → Quaternius GLB | `tools/mixamo_retarget.py` (Blender 5.1.2 headless) | PROVEN (`northern_soul.glb`) |
| Clip vocabulary | 12 KI packs + UAL1/2 + mixamo dir, ~810 clips; KI social = Dance0118, DancePoses, claps, cheers | SHIPPED |
| Pose extraction from video | `pose-estimation` skill (user-level, MediaPipe Tasks) | BUILT + TESTED today |
| Pose sequence comparison (DTW, 8 joint angles) | `compare_poses.py` in same skill | BUILT + TESTED (identity=100.0, cross-segment≈71) |
| Animation creation recipes | `.claude/skills/animation-creation/SKILL.md` | BUILT today |
**Key experimental finding (2026-07-13):** MediaPipe tracks the stylized Quaternius
characters at **94% detection** when ONE character is crop-zoomed to fill the frame
(`crop=140:180:350:420,scale=560:720:flags=lanczos` on a test bed recording). Wide
formation shots detect **0%**. Every capture step below therefore frames a single dancer.
## Pipeline stages
### Stage 1 — Ingest the source video
1. `ffprobe` duration/fps; extract audio (`ffmpeg -vn audio.wav`).
2. **BPM + beat grid**: `librosa.beat.beat_track` (add librosa to the pose-estimation
venv when first needed). Beat times become the dance's `bpm` and the sampling grid.
3. Extract pose: `extract_pose.py video.mp4 --times "<beat grid>" --overlay check.mp4`.
If multi-person/wide: crop-zoom the clearest dancer first. Eyeball the overlay.
4. Extract frames on the beat grid for the vision pass (`ffmpeg -vf select=...`).
### Stage 2 — Choreography breakdown
- **Programmatic move segmentation**: the 8-angle signature (elbows/shoulders/hips/knees)
from the pose JSON gives a per-beat pose vector; a spike in angle-space distance
between consecutive beats = likely move boundary. Cheap, deterministic.
- **Vision pass**: agent reads beat-grid frames and writes a per-segment description
("beats 18: crouched stomp, arms slapping thighs..."). Combines with the programmatic
boundaries — vision names the moves, angles locate them.
- Output: `breakdown.json` — segments with beat ranges, text description, pose signature.
### Stage 3 — Clip card catalog (the one missing build item)
One-time batch job; the enabler for matching. For each dance-relevant clip
(KI Dance/DancePose/claps/cheers + UAL emotes + mixamo pack):
1. Test bed plays the clip on ONE dancer, camera framed close (solo framing per the
94% finding). VideoRecorder captures ~2 loops.
2. `extract_pose.py` on the capture → **pose signature** stored per clip.
3. Delegated vision (pi `nova_describe` / cheap model) writes a **text card** per clip.
4. Output: `assets/dances/catalog/clip_cards.json` — `{clipRef, text, bpm-ish tempo,
energy, pose_signature_file}`. Rebuild only when packs change.
Build item: a `CatalogMode` in the dance test bed (iterate clips → frame solo dancer →
record → next). Everything else is scripting.
### Stage 4 — Matching (segment → clip or composite)
1. **Numeric**: DTW each video segment's angle sequence against every catalog clip
signature (`compare_poses.py` logic). Rank by score.
2. **Split-mask matching for composites**: score arms (4 arm angles) and legs (4 leg
angles) *independently*. If no whole clip scores well but clip A wins arms and clip
B wins legs → propose `{layers:[{mask:"upper",clip:A},{mask:"lower",clip:B}]}`.
3. **Vision tiebreak**: agent compares top-3 candidates' text cards against the
segment description; picks; records rationale.
### Stage 5 — Gap-fill via Mixamo
Segment with no acceptable match → agent emits a **shopping list** (search terms for
mixamo.com; downloads are behind Adobe login, so Jeremy grabs FBXs manually — ~5 min)
→ `mixamo_retarget.py` → new pack in `assets/quaternius/mixamo/` → add to catalog
(Stage 3 for just that pack) → re-match.
### Stage 6 — Emit the dance
Write `assets/dances/<name>.json`: `bpm` from Stage 1, one move per segment, `loops`
from beat counts. Hot-reload shows it immediately if the test bed is running.
### Stage 7 — Verify loop (closes the circle)
1. Test bed plays the dance; camera solo-framed on one dancer; VideoRecorder captures.
2. `extract_pose.py` on the capture → `compare_poses.py` vs source, per segment
(`--a-range/--b-range` from the beat grid).
3. `score_0_100` per segment + `per_joint_error_deg` says WHERE it diverges (arms vs
legs → swap just that layer of a composite). Iterate moves until segments clear a
threshold (start ~65; calibrate).
4. Final deliverable: side-by-side mp4 (`ffmpeg hstack`) + per-segment score table.
## Deliverables ledger
| Item | Status |
|---|---|
| `pose-estimation` skill (extract + compare, venv, models) | DONE 2026-07-13 |
| `animation-creation` skill (project-level recipes) | DONE 2026-07-13 |
| This pipeline doc | DONE 2026-07-13 |
| Test bed `CatalogMode` (solo-frame + record each clip) | TODO — first build item |
| Catalog batch script + `clip_cards.json` | TODO |
| librosa beat grid helper | TODO (trivial, add when needed) |
| Segment/match/emit agent workflow (`/dance-from-video`) | TODO — after catalog |
## Risks / open questions
- **Camera angle mismatch**: source video vs game capture viewpoint differ; world
landmarks + joint angles are view-invariant in principle, but MediaPipe's 3D lift is
weaker at oblique angles. Mitigation: match game camera height/angle roughly to source.
- **Multi-dancer sources**: pick ONE dancer (ideally the leader) and track them; group
formation is authored separately (formations are already a test bed parameter).
- **Catalog scale**: ~810 clips × record+describe is hours of batch time. Start with
the ~40 obviously dance-relevant clips; expand on demand.
- **Score threshold semantics**: 71 = "different segments of the same dance", so
same-move recreations should land higher; calibrate on known pairs before trusting.
- KI clips are polished loops; Mixamo retargets can have foot slide — acceptable for
dance (no locomotion), watch for it.
@@ -0,0 +1,112 @@
# Animation skills adoption — 2026-07-13
Goal: let agents **create** animations and rig them onto GLBs for ariki-game, not just
retarget existing packs. All animation runs on the one shared Quaternius skeleton (65
bones, UE names), so the bottleneck is tooling that gets new motion onto that rig. This
report records the research tiering, what this pass integrated (file authoring only), and
the orchestrator runbook for the install/launch steps an agent must not do.
## Research findings
**Tier 1 — adopt now (integrated or queued for trial this pass):**
- **blender-mcp** (github.com/ahujasid/blender-mcp, MIT, 16k+ stars) — MCP server bridging
the agent to a live Blender via a socket addon; the agent sends arbitrary `bpy` to build
armatures, keyframe, set up IK/NLA, and export GLB. *Why Tier 1:* the one capability the
project was missing — direct programmatic Blender authoring from the agent loop.
- **Blender Toolkit skill** (majiayu000) — Mixamo→custom-rig retarget with fuzzy bone
matching over a WebSocket bridge. *Why Tier 1:* directly comparable to the project's own
`tools/mixamo_retarget.py`; trial it head-to-head and keep the winner.
- **Blender Animation & Rigging Expert skill** — programmatic armatures, IK/FK, drivers,
NLA via MCP. *Why Tier 1:* the deep-blender companion to blender-mcp for non-trivial rigs.
- **Extend our own project skill** (this pass) — the existing `.claude/skills/animation-creation/`
is the cheapest surface; adding Path 5 + gltf-transform keeps everything in one place.
**Tier 2 — trial before committing:**
- **gltf-transform** (gltf-transform.dev, donmccurdy) — headless GLB surgery: inspect,
merge, resample, prune, dedup; same-skeleton clip transplants need no Blender. *Why Tier
2:* documented here and usable via `npx`, but the project's clip-editing volume is
currently low; adopt the recipes, verify the v4 API on first real use.
- **PoseCap** (github.com/CorridorTech/PoseCap) — markerless mocap, video → PEAR model →
SMPL-X poses → Blender keyframes; works on pre-recorded clips; custom-rig retarget is
roadmap-only; UI extension, not headless. *Why Tier 2:* promising video-to-motion path,
but SMPL-X→Quaternius retarget is unbuilt — eval before investing.
- **OpenClaw / freshtechbro Blender pipeline skills** — engine export-settings knowledge.
*Why Tier 2:* useful reference for engine-specific gotchas, redundant once our export
block is canonical.
**Tier 3 — skip for now:**
- **godot-mcp servers** — redundant: the game already has an agent API on port 4329 plus an
in-scene `VideoRecorder`; a Godot MCP adds nothing.
- **DavinciDreams 3D Design Team plugin and other knowledge-only skill packs** — broad and
shallow; the targeted recipes above cover the same ground more concretely.
## Integrated in this pass
File authoring only (no installs, no commits):
- **A — `.mcp.json`**: registered the `blender` MCP server (`uvx blender-mcp`).
- **B — `.claude/skills/animation-creation/SKILL.md`**: added **Path 5 — Author in live
Blender (blender-mcp)** and a **GLB surgery without Blender (gltf-transform)** section,
both pointing at the new reference docs.
- **C — `references/blender-mcp-recipes.md`** (new): `bpy` recipes for setup, keyframing,
IK setup + bake, NLA layering, and an **export block mirrored exactly from
`tools/mixamo_retarget.py`** (`NLA_TRACKS` mode, `export_force_sampling`, size-opt off),
plus gotchas (`*RM` variants, `RESET` clip, one armature/GLB, fps=30, quaternion mode).
- **D — `references/gltf-transform-recipes.md`** (new): CLI/SDK inspect, same-skeleton clip
transplant sketch (flagged `verify against gltf-transform v4 API before first use`),
resample/prune/dedup shrink pass, and when-to-prefer-over-Blender guidance.
## Orchestrator runbook
**Not run by the authoring agent.** The orchestrator (or Jeremy) executes these:
1. **blender-mcp smoke test.** From a shell: `uvx blender-mcp` — confirm the server starts
and binds the socket (Ctrl-C to stop; this only checks installability).
2. **Install the Blender addon.** Download `addon.py` from
github.com/ahujasid/blender-mcp and in Blender 5.1.2
(`/Applications/Blender.app`): Edit → Preferences → Add-ons → Install → select
`addon.py` → enable. Then 3D View sidebar → BlenderMCP → **Connect**.
3. **Reload MCP config.** Restart Claude Code so the `blender` server in `.mcp.json` is
picked up; confirm the `blender` MCP tools (`execute-code`, etc.) are now available.
4. **blender-mcp agent smoke test.** Through the MCP tools: import a game GLB
(`assets/quaternius/kevin/kevin_male_social.glb`), keyframe a wave on `hand_l`
(see `blender-mcp-recipes.md` keyframing recipe), export GLB into
`assets/quaternius/mixamo/`, and confirm the new clip appears in
`scenes/animation_showcase.tscn`.
5. **gltf-transform smoke test.** `npx @gltf-transform/cli inspect
assets/quaternius/kevin/kevin_male_social.glb` — confirm it lists the animations and
their durations. (No install step; `npx` fetches the CLI on demand.)
6. **Skill trials (user-level install at `~/.claude/skills/`).** Install **Blender Toolkit**
(majiayu000) and **Blender Animation & Rigging Expert**. Run one Mixamo clip → Quaternius
retarget through Blender Toolkit and compare the output against
`tools/mixamo_retarget.py` in the dance test bed — keep whichever loses as
reference-only.
7. **PoseCap eval.** Install the PoseCap Blender extension; run one short dance clip →
SMPL-X keyframes; assess quality vs the existing "match video to shipped clips via the
pose-estimation skill" approach **before** investing in SMPL-X→Quaternius retarget.
> **Always ASK Jeremy before any game launch.** Run `tinqs pull` before launching the game
> so the working tree is current.
## Verification
- **Retarget round-trip:** a clip authored via blender-mcp (or retargeted through Blender
Toolkit) plays correctly in the dance test bed (`SCENE=dance_test_bed
bash tools/game.sh spawn` — ask Jeremy first), recorded with the in-scene
`VideoRecorder` to `~/Downloads/*.mp4` and scored against source footage with the
`pose-estimation` skill.
- **gltf-transform clip transplant:** a clip moved between two same-skeleton GLBs via the
SDK recipe plays in `scenes/animation_showcase.tscn` at the expected `<pack>/<ClipName>`,
confirming the channel-target re-pointing worked.
## Open items
- Confirm the gltf-transform v4 SDK call for cross-document animation copy on first real
use (the `copyToDocument` sketch in `gltf-transform-recipes.md` is flagged for this).
- Decide Blender Toolkit vs `tools/mixamo_retarget.py` after the head-to-head retarget
trial (runbook step 6).
- Decide whether to invest in SMPL-X→Quaternius retarget after the PoseCap quality eval
(runbook step 7).