Charlie Li commited on
Commit
e5eeca0
·
1 Parent(s): 75c2932

Initial MuscleMimic research space

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +3 -0
  2. .gitignore +17 -0
  3. .python-version +1 -0
  4. README.md +17 -7
  5. app.py +287 -0
  6. assets/banner.jpg +3 -0
  7. assets/bimanual_model.png +3 -0
  8. assets/fullbody_model.png +3 -0
  9. assets/gait_analysis_run.png +3 -0
  10. assets/gait_analysis_walk.png +3 -0
  11. assets/logo.png +3 -0
  12. assets/pipeline_overview.png +3 -0
  13. config.py +235 -0
  14. requirements.txt +1 -0
  15. style.css +495 -0
  16. uv.lock +0 -0
  17. videos/blog/airkick.mp4 +3 -0
  18. videos/blog/backwards_walking.mp4 +3 -0
  19. videos/blog/bimanual_out.mp4 +3 -0
  20. videos/blog/dancing.mp4 +3 -0
  21. videos/blog/drinking_water.mp4 +3 -0
  22. videos/blog/jumpingjack.mp4 +3 -0
  23. videos/blog/lifting_box.mp4 +3 -0
  24. videos/blog/walking_running.mp4 +3 -0
  25. videos/blog/walking_turning.mp4 +3 -0
  26. videos/blog/waving.mp4 +3 -0
  27. videos/demo/mm-100M-s1/KIT_10_RightTurn02_poses/eval_MyoFullBody.mp4 +3 -0
  28. videos/demo/mm-100M-s1/KIT_10_WalkingStraightBackwards07_poses/eval_MyoFullBody.mp4 +3 -0
  29. videos/demo/mm-100M-s1/KIT_11_LeftTurn05_poses/eval_MyoFullBody.mp4 +3 -0
  30. videos/demo/mm-100M-s1/KIT_11_WalkInCounterClockwiseCircle02_poses/eval_MyoFullBody.mp4 +3 -0
  31. videos/demo/mm-100M-s1/KIT_11_WalkingStraightBackwards09_1_poses/eval_MyoFullBody.mp4 +3 -0
  32. videos/demo/mm-100M-s1/KIT_11_WalkingStraightForwards05_poses/eval_MyoFullBody.mp4 +3 -0
  33. videos/demo/mm-100M-s1/KIT_12_LeftTurn03_poses/eval_MyoFullBody.mp4 +3 -0
  34. videos/demo/mm-100M-s1/KIT_12_WalkInClockwiseCircle11_poses/eval_MyoFullBody.mp4 +3 -0
  35. videos/demo/mm-100M-s1/KIT_12_WalkingStraightBackwards05_poses/eval_MyoFullBody.mp4 +3 -0
  36. videos/demo/mm-100M-s1/KIT_167_walking_medium03_poses/eval_MyoFullBody.mp4 +3 -0
  37. videos/demo/mm-100M-s1/KIT_314_walking_run09_poses/eval_MyoFullBody.mp4 +3 -0
  38. videos/demo/mm-100M-s1/KIT_314_walking_slow03_poses/eval_MyoFullBody.mp4 +3 -0
  39. videos/demo/mm-100M-s1/KIT_348_turn_right06_poses/eval_MyoFullBody.mp4 +3 -0
  40. videos/demo/mm-100M-s1/KIT_359_turn_left05_poses/eval_MyoFullBody.mp4 +3 -0
  41. videos/demo/mm-100M-s1/KIT_3_turn_right04_poses/eval_MyoFullBody.mp4 +3 -0
  42. videos/demo/mm-100M-s1/KIT_424_turn_right02_poses/eval_MyoFullBody.mp4 +3 -0
  43. videos/demo/mm-100M-s1/KIT_424_walking_fast10_poses/eval_MyoFullBody.mp4 +3 -0
  44. videos/demo/mm-100M-s1/KIT_4_WalkInClockwiseCircle04_poses/eval_MyoFullBody.mp4 +3 -0
  45. videos/demo/mm-100M-s1/KIT_4_WalkingStraightBackwards01_poses/eval_MyoFullBody.mp4 +3 -0
  46. videos/demo/mm-100M-s1/KIT_6_WalkInCounterClockwiseCircle04_1_poses/eval_MyoFullBody.mp4 +3 -0
  47. videos/demo/mm-100M-s1/KIT_6_WalkInCounterClockwiseCircle06_1_poses/eval_MyoFullBody.mp4 +3 -0
  48. videos/demo/mm-100M-s1/KIT_6_WalkingStraightBackwards04_poses/eval_MyoFullBody.mp4 +3 -0
  49. videos/demo/mm-100M-s1/KIT_7_LeftTurn06_poses/eval_MyoFullBody.mp4 +3 -0
  50. videos/demo/mm-100M-s1/KIT_7_WalkingStraightBackwards04_poses/eval_MyoFullBody.mp4 +3 -0
.gitattributes CHANGED
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.mp4 filter=lfs diff=lfs merge=lfs -text
37
+ *.png filter=lfs diff=lfs merge=lfs -text
38
+ *.jpg filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+
6
+ # Virtual environments
7
+ .venv/
8
+ venv/
9
+
10
+ # OS / editor
11
+ .DS_Store
12
+ .idea/
13
+ .vscode/
14
+
15
+ # Gradio cache
16
+ .gradio/
17
+ flagged/
.python-version ADDED
@@ -0,0 +1 @@
 
 
1
+ 3.11
README.md CHANGED
@@ -1,14 +1,24 @@
1
  ---
2
- title: Musclemimic Space
3
- emoji: 🔥
4
- colorFrom: pink
5
- colorTo: green
6
  sdk: gradio
7
- sdk_version: 6.13.0
8
  app_file: app.py
9
- pinned: false
 
 
 
 
 
 
10
  license: apache-2.0
11
  short_description: MuscleMimic hugging face space
12
  ---
13
 
14
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
1
  ---
2
+ title: MuscleMimic Research Space
3
+ emoji: "\U0001F4C4"
4
+ colorFrom: gray
5
+ colorTo: blue
6
  sdk: gradio
7
+ sdk_version: 5.35.0
8
  app_file: app.py
9
+ pinned: true
10
+ models:
11
+ - amathislab/mm-fullbody-base
12
+ - amathislab/mm-bimanual-v0
13
+ datasets:
14
+ - amathislab/musclemimic-retargeted
15
+ - amathislab/musclemimic-bimanual-retargeted
16
  license: apache-2.0
17
  short_description: MuscleMimic hugging face space
18
  ---
19
 
20
+ # MuscleMimic Research Space
21
+
22
+ A companion Space for [MuscleMimic](https://arxiv.org/abs/2603.25544) with rollout videos, checkpoint comparisons, and figures from the paper.
23
+
24
+ Paper: https://huggingface.co/papers/2603.25544
app.py ADDED
@@ -0,0 +1,287 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from html import escape
2
+ from urllib.parse import quote
3
+
4
+ import gradio as gr
5
+
6
+ from config import (
7
+ BASE_DIR,
8
+ CATEGORIES,
9
+ CITATION_BIBTEX,
10
+ DEFAULT_MOTION,
11
+ HIGHLIGHT_VIDEOS,
12
+ MODELS,
13
+ MODEL_KEYS,
14
+ RESOURCE_LINKS,
15
+ get_motion_metadata,
16
+ get_motions_by_category,
17
+ get_video_path,
18
+ label_to_key,
19
+ )
20
+
21
+ gr.set_static_paths(paths=[str(BASE_DIR / "videos"), str(BASE_DIR / "assets")])
22
+ FILE_ROUTE_PREFIX = "/gradio_api/file=" if int(gr.__version__.split(".", 1)[0]) >= 6 else "/file="
23
+
24
+ with open(BASE_DIR / "style.css", encoding="utf-8") as css_file:
25
+ CUSTOM_CSS = css_file.read()
26
+
27
+
28
+ def static_src(*relative_parts: str) -> str:
29
+ return file_src(BASE_DIR.joinpath(*relative_parts))
30
+
31
+
32
+ def file_src(path) -> str:
33
+ return f"{FILE_ROUTE_PREFIX}{quote(str(path), safe='/')}"
34
+
35
+
36
+ def render_resource_links() -> str:
37
+ cards = []
38
+ for item in RESOURCE_LINKS:
39
+ cards.append(
40
+ f"""
41
+ <a class="mm-link-card" href="{escape(item["url"])}" target="_blank" rel="noreferrer">
42
+ <span class="mm-link-title">{escape(item["label"])}</span>
43
+ <span class="mm-link-note">{escape(item["note"])}</span>
44
+ </a>
45
+ """
46
+ )
47
+ return "".join(cards)
48
+
49
+
50
+ def build_hero_html() -> str:
51
+ return f"""
52
+ <section id="top" class="mm-hero">
53
+ <div class="mm-brand">
54
+ <img src="{static_src("assets", "logo.png")}" alt="MuscleMimic logo">
55
+ <span>MuscleMimic Research Space</span>
56
+ </div>
57
+ <h1>Checkpoint comparison and policy rollouts</h1>
58
+ <p class="mm-hero-lede">
59
+ MuscleMimic lets us train and evaluate many checkpoints and training recipes at scale.
60
+ Here we showcase a few interesting ones: side-by-side checkpoint comparisons and
61
+ policy rollouts across locomotion, manipulation, and dynamic motions.
62
+ </p>
63
+ <div class="mm-nav">
64
+ <a href="#explorer">Checkpoint comparison</a>
65
+ <a href="#highlights">Policy rollouts</a>
66
+ <a href="#resources">Paper and release links</a>
67
+ <a href="#citation">Citation</a>
68
+ </div>
69
+ </section>
70
+ """
71
+
72
+
73
+ def build_explorer_intro_html() -> str:
74
+ return """
75
+ <section id="explorer" class="mm-section">
76
+ <div class="mm-section-head">
77
+ <p class="mm-overline">Checkpoint Comparison</p>
78
+ <h2>Checkpoint comparison on KIT locomotion motions</h2>
79
+ <p>
80
+ Compare MyoFullBody checkpoints on KIT locomotion motions.
81
+ The colored character is the reference motion and the other character is the rollout.
82
+ </p>
83
+ </div>
84
+ </section>
85
+ """
86
+
87
+
88
+ def build_highlights_html() -> str:
89
+ cards = []
90
+ for item in HIGHLIGHT_VIDEOS:
91
+ cards.append(
92
+ f"""
93
+ <article class="mm-video-card">
94
+ <div class="mm-video-shell">
95
+ <video autoplay loop muted playsinline preload="metadata">
96
+ <source src="{static_src("videos", "blog", item["file"])}" type="video/mp4">
97
+ </video>
98
+ </div>
99
+ <div class="mm-video-meta">
100
+ <span class="mm-tag">{escape(item["tag"])}</span>
101
+ <h3>{escape(item["label"])}</h3>
102
+ </div>
103
+ </article>
104
+ """
105
+ )
106
+
107
+ return f"""
108
+ <section id="highlights" class="mm-section">
109
+ <div class="mm-section-head">
110
+ <p class="mm-overline">Policy Rollouts</p>
111
+ <h2>Policy rollouts across locomotion, manipulation, and dynamic motions</h2>
112
+ <p>
113
+ Selected examples spanning locomotion, object interaction, and more dynamic motions.
114
+ In each video, the blue or purple character is the reference motion.
115
+ </p>
116
+ </div>
117
+ <div class="mm-video-grid">
118
+ {''.join(cards)}
119
+ </div>
120
+ </section>
121
+ """
122
+
123
+
124
+ def build_resources_html() -> str:
125
+ return f"""
126
+ <section id="resources" class="mm-section">
127
+ <div class="mm-section-head">
128
+ <p class="mm-overline">Resources</p>
129
+ <h2>Paper and release links</h2>
130
+ <p>
131
+ Primary links for the paper, code, released checkpoint, and retargeted dataset.
132
+ </p>
133
+ </div>
134
+ <div class="mm-link-strip">
135
+ {render_resource_links()}
136
+ </div>
137
+ </section>
138
+ """
139
+
140
+
141
+ def build_citation_html() -> str:
142
+ return f"""
143
+ <section id="citation" class="mm-section">
144
+ <div class="mm-section-head">
145
+ <p class="mm-overline">Citation</p>
146
+ <h2>Cite MuscleMimic</h2>
147
+ <p>
148
+ If you use MuscleMimic in your research, please cite the paper:
149
+ </p>
150
+ </div>
151
+ <pre class="mm-bibtex"><code>{escape(CITATION_BIBTEX)}</code></pre>
152
+ </section>
153
+ """
154
+
155
+
156
+ def build_motion_summary_html(motion_label: str) -> str:
157
+ if not motion_label:
158
+ motion_label = DEFAULT_MOTION
159
+
160
+ motion_meta = get_motion_metadata(motion_label)
161
+
162
+ return f"""
163
+ <div class="mm-panel-head">
164
+ <div>
165
+ <p class="mm-overline">Selected Motion</p>
166
+ <h3>{escape(motion_label)}</h3>
167
+ <p>
168
+ Side-by-side comparison on a KIT locomotion trajectory from
169
+ <strong>{escape(motion_meta["category"])}</strong>.
170
+ </p>
171
+ </div>
172
+ <div class="mm-chip-row">
173
+ <span class="mm-chip">Dataset: {escape(motion_meta["dataset"])}</span>
174
+ <span class="mm-chip">Category: {escape(motion_meta["category"])}</span>
175
+ <span class="mm-chip">Reference: blue / purple actor</span>
176
+ </div>
177
+ </div>
178
+ """
179
+
180
+
181
+ def get_motion_assets(motion_label: str):
182
+ if not motion_label:
183
+ motion_label = DEFAULT_MOTION
184
+
185
+ motion_key = label_to_key(motion_label)
186
+ return (
187
+ build_motion_summary_html(motion_label),
188
+ *[get_video_path(model_key, motion_key) for model_key in MODEL_KEYS],
189
+ )
190
+
191
+
192
+ def update_explorer(category: str, current_motion: str):
193
+ choices = get_motions_by_category(category)
194
+ next_motion = current_motion if current_motion in choices else choices[0]
195
+ summary_html, *video_paths = get_motion_assets(next_motion)
196
+ return gr.Dropdown(choices=choices, value=next_motion), summary_html, *video_paths
197
+
198
+
199
+ def update_motion_assets(motion_label: str):
200
+ return get_motion_assets(motion_label)
201
+
202
+
203
+ def build_model_card_head(model_key: str) -> str:
204
+ model = MODELS[model_key]
205
+ return f"""
206
+ <div class="mm-compare-head">
207
+ <p class="mm-overline">Checkpoint</p>
208
+ <h3>{escape(model["label"])}</h3>
209
+ <p class="mm-compare-desc">{escape(model["description"])}</p>
210
+ </div>
211
+ """
212
+
213
+
214
+ with gr.Blocks(title="MuscleMimic Research Space") as app:
215
+ gr.HTML(build_hero_html())
216
+ gr.HTML(build_explorer_intro_html())
217
+
218
+ with gr.Row(elem_classes="mm-controls-shell", equal_height=False):
219
+ category_dd = gr.Dropdown(
220
+ choices=CATEGORIES,
221
+ value="All",
222
+ label="Motion Family",
223
+ info="Filter the KIT / KINESIS set by locomotion subtype.",
224
+ elem_classes="mm-select",
225
+ scale=1,
226
+ min_width=280,
227
+ )
228
+ motion_dd = gr.Dropdown(
229
+ choices=get_motions_by_category("All"),
230
+ value=DEFAULT_MOTION,
231
+ label="Motion Clip",
232
+ info="Choose a KIT locomotion trajectory for checkpoint comparison.",
233
+ elem_classes="mm-select",
234
+ scale=1,
235
+ min_width=280,
236
+ )
237
+
238
+ _card_class_suffix = {
239
+ "mm-10m-1": "mm-compare-card-10m",
240
+ "mm-base-e": "mm-compare-card-base-e",
241
+ "mm-100M-s1": "mm-compare-card-100m",
242
+ "mm-fullbody-base": "mm-compare-card-fullbody-base",
243
+ }
244
+
245
+ initial = get_motion_assets(DEFAULT_MOTION)
246
+ initial_summary_html = initial[0]
247
+ initial_video_paths = list(initial[1:])
248
+
249
+ vids = []
250
+ with gr.Column(elem_classes="mm-compare-panel"):
251
+ selected_motion_html = gr.HTML(initial_summary_html)
252
+ with gr.Row(elem_classes="mm-compare-grid", equal_height=False):
253
+ for model_key, video_path in zip(MODEL_KEYS, initial_video_paths):
254
+ suffix = _card_class_suffix.get(model_key)
255
+ card_classes = ["mm-compare-card"]
256
+ if suffix:
257
+ card_classes.append(suffix)
258
+ with gr.Column(elem_classes=card_classes):
259
+ gr.HTML(build_model_card_head(model_key))
260
+ vids.append(
261
+ gr.Video(
262
+ value=video_path,
263
+ autoplay=True,
264
+ loop=True,
265
+ show_label=False,
266
+ container=False,
267
+ elem_classes="mm-compare-video",
268
+ )
269
+ )
270
+
271
+ gr.HTML(build_highlights_html())
272
+ gr.HTML(build_resources_html())
273
+ gr.HTML(build_citation_html())
274
+
275
+ category_dd.change(
276
+ fn=update_explorer,
277
+ inputs=[category_dd, motion_dd],
278
+ outputs=[motion_dd, selected_motion_html, *vids],
279
+ )
280
+ motion_dd.change(
281
+ fn=update_motion_assets,
282
+ inputs=[motion_dd],
283
+ outputs=[selected_motion_html, *vids],
284
+ )
285
+
286
+ if __name__ == "__main__":
287
+ app.launch(css=CUSTOM_CSS)
assets/banner.jpg ADDED

Git LFS Details

  • SHA256: 239266d0b0d3e6e84d76939717bb9c809e3d44b2659f7bbf9d34c7e339d8d239
  • Pointer size: 130 Bytes
  • Size of remote file: 62.6 kB
assets/bimanual_model.png ADDED

Git LFS Details

  • SHA256: 24289b723fb395f383cbd13a182dd93dbfd7e88d60a205008072aacd3b76a044
  • Pointer size: 132 Bytes
  • Size of remote file: 1.92 MB
assets/fullbody_model.png ADDED

Git LFS Details

  • SHA256: 1e183101ddef8224aea2103b2f8e02698164b0c9b8b7624bbe10acffba335bd0
  • Pointer size: 132 Bytes
  • Size of remote file: 2.17 MB
assets/gait_analysis_run.png ADDED

Git LFS Details

  • SHA256: c25a4370f5049783c06670e5db22349caa41f162ae7120b59b19dac8e447defa
  • Pointer size: 132 Bytes
  • Size of remote file: 1.5 MB
assets/gait_analysis_walk.png ADDED

Git LFS Details

  • SHA256: 57a0ef5ebc38948f76f3304e4966b54346d2e8247475fc00e85a0aea6b9c34c3
  • Pointer size: 132 Bytes
  • Size of remote file: 1.77 MB
assets/logo.png ADDED

Git LFS Details

  • SHA256: 59fa884844ad00881dfcd3275c8264cbe823ab71d11bd5c10ab4bc13109ab29a
  • Pointer size: 130 Bytes
  • Size of remote file: 61.9 kB
assets/pipeline_overview.png ADDED

Git LFS Details

  • SHA256: 148fad6329b8ec4270b20875e60b4c10bb54f8dbbed8b55071f9d63afa77c723
  • Pointer size: 131 Bytes
  • Size of remote file: 526 kB
config.py ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+ BASE_DIR = Path(__file__).parent
4
+
5
+ MODELS = {
6
+ "mm-10m-1": {
7
+ "label": "MM-10M",
8
+ "accent": "#9a6237",
9
+ "description": "10M-parameter policy.",
10
+ },
11
+ "mm-base-e": {
12
+ "label": "MM-Base-E",
13
+ "accent": "#2f6a73",
14
+ "description": "Trained with a strong energy regularization.",
15
+ },
16
+ "mm-100M-s1": {
17
+ "label": "MM-100M",
18
+ "accent": "#7a4c8f",
19
+ "description": "100M-parameter policy.",
20
+ },
21
+ "mm-fullbody-base": {
22
+ "label": "MM-FullBody-Base",
23
+ "accent": "#c13a5b",
24
+ "description": "Released baseline checkpoint (50M parameters).",
25
+ },
26
+ }
27
+
28
+ MODEL_KEYS = list(MODELS.keys())
29
+
30
+ MOTIONS = {
31
+ "KIT_314_walking_slow03_poses": {
32
+ "label": "Walking · Slow",
33
+ "category": "Walking",
34
+ "dataset": "KIT / KINESIS",
35
+ },
36
+ "KIT_167_walking_medium03_poses": {
37
+ "label": "Walking · Medium",
38
+ "category": "Walking",
39
+ "dataset": "KIT / KINESIS",
40
+ },
41
+ "KIT_424_walking_fast10_poses": {
42
+ "label": "Walking · Fast",
43
+ "category": "Walking",
44
+ "dataset": "KIT / KINESIS",
45
+ },
46
+ "KIT_314_walking_run09_poses": {
47
+ "label": "Running",
48
+ "category": "Walking",
49
+ "dataset": "KIT / KINESIS",
50
+ },
51
+ "KIT_11_WalkingStraightForwards05_poses": {
52
+ "label": "Walk Straight Forward",
53
+ "category": "Walking",
54
+ "dataset": "KIT / KINESIS",
55
+ },
56
+ "KIT_4_WalkingStraightBackwards01_poses": {
57
+ "label": "Walk Backwards · Subject 4",
58
+ "category": "Backwards",
59
+ "dataset": "KIT / KINESIS",
60
+ },
61
+ "KIT_6_WalkingStraightBackwards04_poses": {
62
+ "label": "Walk Backwards · Subject 6",
63
+ "category": "Backwards",
64
+ "dataset": "KIT / KINESIS",
65
+ },
66
+ "KIT_7_WalkingStraightBackwards04_poses": {
67
+ "label": "Walk Backwards · Subject 7",
68
+ "category": "Backwards",
69
+ "dataset": "KIT / KINESIS",
70
+ },
71
+ "KIT_10_WalkingStraightBackwards07_poses": {
72
+ "label": "Walk Backwards · Subject 10",
73
+ "category": "Backwards",
74
+ "dataset": "KIT / KINESIS",
75
+ },
76
+ "KIT_11_WalkingStraightBackwards09_1_poses": {
77
+ "label": "Walk Backwards · Subject 11",
78
+ "category": "Backwards",
79
+ "dataset": "KIT / KINESIS",
80
+ },
81
+ "KIT_12_WalkingStraightBackwards05_poses": {
82
+ "label": "Walk Backwards · Subject 12",
83
+ "category": "Backwards",
84
+ "dataset": "KIT / KINESIS",
85
+ },
86
+ "KIT_3_turn_right04_poses": {
87
+ "label": "Turn Right · Subject 3",
88
+ "category": "Turning",
89
+ "dataset": "KIT / KINESIS",
90
+ },
91
+ "KIT_8_RightTurn10_poses": {
92
+ "label": "Turn Right · Subject 8",
93
+ "category": "Turning",
94
+ "dataset": "KIT / KINESIS",
95
+ },
96
+ "KIT_10_RightTurn02_poses": {
97
+ "label": "Turn Right · Subject 10",
98
+ "category": "Turning",
99
+ "dataset": "KIT / KINESIS",
100
+ },
101
+ "KIT_348_turn_right06_poses": {
102
+ "label": "Turn Right · Subject 348",
103
+ "category": "Turning",
104
+ "dataset": "KIT / KINESIS",
105
+ },
106
+ "KIT_424_turn_right02_poses": {
107
+ "label": "Turn Right · Subject 424",
108
+ "category": "Turning",
109
+ "dataset": "KIT / KINESIS",
110
+ },
111
+ "KIT_7_LeftTurn06_poses": {
112
+ "label": "Turn Left · Subject 7",
113
+ "category": "Turning",
114
+ "dataset": "KIT / KINESIS",
115
+ },
116
+ "KIT_11_LeftTurn05_poses": {
117
+ "label": "Turn Left · Subject 11",
118
+ "category": "Turning",
119
+ "dataset": "KIT / KINESIS",
120
+ },
121
+ "KIT_12_LeftTurn03_poses": {
122
+ "label": "Turn Left · Subject 12",
123
+ "category": "Turning",
124
+ "dataset": "KIT / KINESIS",
125
+ },
126
+ "KIT_359_turn_left05_poses": {
127
+ "label": "Turn Left · Subject 359",
128
+ "category": "Turning",
129
+ "dataset": "KIT / KINESIS",
130
+ },
131
+ "KIT_4_WalkInClockwiseCircle04_poses": {
132
+ "label": "Clockwise Circle · Subject 4",
133
+ "category": "Circular",
134
+ "dataset": "KIT / KINESIS",
135
+ },
136
+ "KIT_9_WalkInClockwiseCircle04_poses": {
137
+ "label": "Clockwise Circle · Subject 9a",
138
+ "category": "Circular",
139
+ "dataset": "KIT / KINESIS",
140
+ },
141
+ "KIT_9_WalkInClockwiseCircle06_poses": {
142
+ "label": "Clockwise Circle · Subject 9b",
143
+ "category": "Circular",
144
+ "dataset": "KIT / KINESIS",
145
+ },
146
+ "KIT_12_WalkInClockwiseCircle11_poses": {
147
+ "label": "Clockwise Circle · Subject 12",
148
+ "category": "Circular",
149
+ "dataset": "KIT / KINESIS",
150
+ },
151
+ "KIT_6_WalkInCounterClockwiseCircle04_1_poses": {
152
+ "label": "Counter-Clockwise Circle · Subject 6a",
153
+ "category": "Circular",
154
+ "dataset": "KIT / KINESIS",
155
+ },
156
+ "KIT_6_WalkInCounterClockwiseCircle06_1_poses": {
157
+ "label": "Counter-Clockwise Circle · Subject 6b",
158
+ "category": "Circular",
159
+ "dataset": "KIT / KINESIS",
160
+ },
161
+ "KIT_11_WalkInCounterClockwiseCircle02_poses": {
162
+ "label": "Counter-Clockwise Circle · Subject 11",
163
+ "category": "Circular",
164
+ "dataset": "KIT / KINESIS",
165
+ },
166
+ }
167
+
168
+ CATEGORIES = ["All", "Walking", "Backwards", "Turning", "Circular"]
169
+ DEFAULT_MOTION = "Walking · Medium"
170
+
171
+ _LABEL_TO_KEY = {metadata["label"]: motion_key for motion_key, metadata in MOTIONS.items()}
172
+
173
+
174
+ def label_to_key(label: str) -> str:
175
+ return _LABEL_TO_KEY[label]
176
+
177
+
178
+ def get_motion_metadata(label: str) -> dict[str, str]:
179
+ return MOTIONS[label_to_key(label)]
180
+
181
+
182
+ def get_video_path(model_key: str, motion_key: str) -> str:
183
+ path = BASE_DIR / "videos" / "demo" / model_key / motion_key / "eval_MyoFullBody.mp4"
184
+ return str(path)
185
+
186
+
187
+ def get_motions_by_category(category: str) -> list[str]:
188
+ if category == "All":
189
+ return [metadata["label"] for metadata in MOTIONS.values()]
190
+ return [
191
+ metadata["label"]
192
+ for metadata in MOTIONS.values()
193
+ if metadata["category"] == category
194
+ ]
195
+
196
+
197
+ CITATION_BIBTEX = """@article{li2026towards,
198
+ title={Towards Embodied AI with MuscleMimic: Unlocking full-body musculoskeletal motor learning at scale},
199
+ author={Li, Chengkun and Wang, Cheryl and Ziliotto, Bianca and Simos, Merkourios and Kovecses, Jozsef and Durandau, Guillaume and Mathis, Alexander},
200
+ journal={arXiv preprint arXiv:2603.25544},
201
+ year={2026}
202
+ }"""
203
+
204
+
205
+ RESOURCE_LINKS = [
206
+ {
207
+ "label": "Paper",
208
+ "url": "https://arxiv.org/abs/2603.25544",
209
+ "note": "Manuscript and supplementary figures",
210
+ },
211
+ {
212
+ "label": "Code",
213
+ "url": "https://github.com/amathislab/musclemimic",
214
+ "note": "Training and evaluation codebase",
215
+ },
216
+ {
217
+ "label": "Checkpoint",
218
+ "url": "https://huggingface.co/amathislab/mm-fullbody-base",
219
+ "note": "Released pretrained full-body model",
220
+ },
221
+ {
222
+ "label": "Dataset",
223
+ "url": "https://huggingface.co/datasets/amathislab/musclemimic-retargeted",
224
+ "note": "Retargeted motion dataset",
225
+ },
226
+ ]
227
+
228
+ HIGHLIGHT_VIDEOS = [
229
+ {"file": "walking_running.mp4", "label": "Walking And Running", "tag": "Locomotion"},
230
+ {"file": "walking_turning.mp4", "label": "Walking And Turning", "tag": "Locomotion"},
231
+ {"file": "lifting_box.mp4", "label": "Lifting Box", "tag": "Manipulation"},
232
+ {"file": "drinking_water.mp4", "label": "Drinking Water", "tag": "Manipulation"},
233
+ {"file": "dancing.mp4", "label": "Dancing", "tag": "Dynamic Motion"},
234
+ {"file": "jumpingjack.mp4", "label": "Jumping Jack", "tag": "Dynamic Motion"},
235
+ ]
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ gradio>=5.0.0
style.css ADDED
@@ -0,0 +1,495 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import url("https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&display=swap");
2
+
3
+ :root {
4
+ --mm-bg: #f3f4f6;
5
+ --mm-surface: #ffffff;
6
+ --mm-surface-soft: #f8f9fb;
7
+ --mm-ink: #111827;
8
+ --mm-ink-soft: #4b5563;
9
+ --mm-muted: #6b7280;
10
+ --mm-line: #d9dee5;
11
+ --mm-accent: #244b57;
12
+ --mm-accent-soft: #eef4f6;
13
+ --mm-shadow: 0 10px 30px rgba(15, 23, 42, 0.06);
14
+ color-scheme: light;
15
+ }
16
+
17
+ html.dark,
18
+ body.dark,
19
+ :root[data-theme="dark"],
20
+ html[data-theme="dark"],
21
+ body[data-theme="dark"],
22
+ .dark,
23
+ .gradio-container.dark {
24
+ --mm-bg: #0b0f14;
25
+ --mm-surface: #121821;
26
+ --mm-surface-soft: #18212c;
27
+ --mm-ink: #f3f6fb;
28
+ --mm-ink-soft: #c8d2de;
29
+ --mm-muted: #96a3b3;
30
+ --mm-line: rgba(175, 189, 204, 0.18);
31
+ --mm-accent: #9cc1cb;
32
+ --mm-accent-soft: rgba(156, 193, 203, 0.14);
33
+ --mm-shadow: 0 16px 40px rgba(0, 0, 0, 0.28);
34
+ color-scheme: dark;
35
+ }
36
+
37
+ html,
38
+ body {
39
+ margin: 0;
40
+ background: var(--mm-bg) !important;
41
+ }
42
+
43
+ body {
44
+ color: var(--mm-ink);
45
+ font-family: "Manrope", -apple-system, BlinkMacSystemFont, sans-serif;
46
+ }
47
+
48
+ .gradio-container {
49
+ max-width: 1180px !important;
50
+ margin: 0 auto !important;
51
+ padding: 24px 24px 56px !important;
52
+ background: transparent !important;
53
+ color: var(--mm-ink) !important;
54
+ font-family: "Manrope", -apple-system, BlinkMacSystemFont, sans-serif !important;
55
+ --body-background-fill: var(--mm-bg);
56
+ --body-background-fill-dark: var(--mm-bg);
57
+ --background-fill-primary: var(--mm-surface);
58
+ --background-fill-secondary: var(--mm-surface-soft);
59
+ --block-background-fill: var(--mm-surface);
60
+ --block-border-color: var(--mm-line);
61
+ --block-label-text-color: var(--mm-ink);
62
+ --block-title-text-color: var(--mm-ink);
63
+ --body-text-color: var(--mm-ink);
64
+ --body-text-color-subdued: var(--mm-muted);
65
+ --input-background-fill: var(--mm-surface-soft);
66
+ --input-border-color: var(--mm-line);
67
+ --input-border-color-focus: var(--mm-accent);
68
+ --input-placeholder-color: var(--mm-muted);
69
+ --color-accent: var(--mm-accent);
70
+ --color-accent-soft: var(--mm-accent-soft);
71
+ }
72
+
73
+ .gradio-container a {
74
+ color: inherit;
75
+ }
76
+
77
+ .mm-overline {
78
+ margin: 0 0 0.45rem;
79
+ color: var(--mm-muted);
80
+ font-size: 0.73rem;
81
+ font-weight: 700;
82
+ letter-spacing: 0.08em;
83
+ text-transform: uppercase;
84
+ }
85
+
86
+ .mm-hero {
87
+ display: flex;
88
+ flex-direction: column;
89
+ gap: 0.9rem;
90
+ padding: 1.5rem 1.6rem;
91
+ border: 1px solid var(--mm-line);
92
+ border-radius: 16px;
93
+ background: var(--mm-surface);
94
+ box-shadow: var(--mm-shadow);
95
+ }
96
+
97
+ .mm-brand {
98
+ display: flex;
99
+ align-items: center;
100
+ gap: 0.75rem;
101
+ }
102
+
103
+ .mm-brand img {
104
+ width: 42px;
105
+ height: 42px;
106
+ border: 1px solid var(--mm-line);
107
+ border-radius: 12px;
108
+ background: var(--mm-surface-soft);
109
+ padding: 0.3rem;
110
+ box-sizing: border-box;
111
+ }
112
+
113
+ .mm-brand span {
114
+ color: var(--mm-muted);
115
+ font-size: 0.88rem;
116
+ font-weight: 700;
117
+ letter-spacing: 0.06em;
118
+ text-transform: uppercase;
119
+ }
120
+
121
+ .mm-hero h1 {
122
+ margin: 0;
123
+ max-width: 14ch;
124
+ color: var(--mm-ink);
125
+ font-size: clamp(2rem, 4vw, 3rem);
126
+ font-weight: 800;
127
+ line-height: 1.05;
128
+ }
129
+
130
+ .mm-hero-lede {
131
+ max-width: 64ch;
132
+ margin: 0;
133
+ color: var(--mm-ink-soft);
134
+ font-size: 1rem;
135
+ line-height: 1.72;
136
+ }
137
+
138
+ .mm-nav {
139
+ display: flex;
140
+ flex-wrap: wrap;
141
+ gap: 0.75rem;
142
+ }
143
+
144
+ .mm-nav a {
145
+ padding: 0.5rem 0.8rem;
146
+ border: 1px solid var(--mm-line);
147
+ border-radius: 999px;
148
+ background: var(--mm-surface-soft);
149
+ color: var(--mm-ink-soft);
150
+ font-size: 0.88rem;
151
+ font-weight: 700;
152
+ text-decoration: none;
153
+ transition: border-color 0.18s ease, color 0.18s ease;
154
+ }
155
+
156
+ .mm-nav a:hover {
157
+ border-color: var(--mm-accent);
158
+ background: var(--mm-surface);
159
+ color: var(--mm-ink);
160
+ }
161
+
162
+ .mm-section {
163
+ margin-top: 2rem;
164
+ }
165
+
166
+ .mm-section-head {
167
+ max-width: 780px;
168
+ margin-bottom: 1rem;
169
+ }
170
+
171
+ .mm-section-head h2 {
172
+ margin: 0.15rem 0 0.6rem;
173
+ color: var(--mm-ink);
174
+ font-size: clamp(1.6rem, 3vw, 2.25rem);
175
+ font-weight: 800;
176
+ line-height: 1.12;
177
+ }
178
+
179
+ .mm-section-head p {
180
+ margin: 0;
181
+ color: var(--mm-ink-soft);
182
+ font-size: 1rem;
183
+ line-height: 1.75;
184
+ }
185
+
186
+ .mm-video-grid {
187
+ display: grid;
188
+ grid-template-columns: repeat(2, minmax(0, 1fr));
189
+ gap: 1rem;
190
+ }
191
+
192
+ .mm-video-card,
193
+ .mm-compare-card,
194
+ .mm-link-card {
195
+ overflow: hidden;
196
+ border: 1px solid var(--mm-line);
197
+ border-radius: 14px;
198
+ background: var(--mm-surface);
199
+ box-shadow: var(--mm-shadow);
200
+ }
201
+
202
+ .mm-video-shell {
203
+ overflow: hidden;
204
+ background: #0f172a;
205
+ aspect-ratio: 16 / 10;
206
+ }
207
+
208
+ .mm-video-shell video {
209
+ display: block;
210
+ width: 100%;
211
+ height: 100%;
212
+ object-fit: cover;
213
+ }
214
+
215
+ .mm-video-meta {
216
+ padding: 0.9rem 1rem 1rem;
217
+ }
218
+
219
+ .mm-video-meta h3,
220
+ .mm-compare-head h3 {
221
+ margin: 0;
222
+ color: var(--mm-ink);
223
+ font-size: 1rem;
224
+ font-weight: 700;
225
+ }
226
+
227
+ .mm-tag {
228
+ display: inline-flex;
229
+ margin-bottom: 0.6rem;
230
+ padding: 0.25rem 0.55rem;
231
+ border-radius: 999px;
232
+ background: var(--mm-accent-soft);
233
+ color: var(--mm-accent);
234
+ font-size: 0.72rem;
235
+ font-weight: 700;
236
+ letter-spacing: 0.04em;
237
+ text-transform: uppercase;
238
+ }
239
+
240
+ .mm-controls-shell {
241
+ margin-top: 0.6rem;
242
+ padding: 0.4rem 0.5rem 0;
243
+ border: 1px solid var(--mm-line);
244
+ border-radius: 14px;
245
+ background: var(--mm-surface);
246
+ box-shadow: var(--mm-shadow);
247
+ overflow: visible !important;
248
+ position: relative;
249
+ z-index: 20;
250
+ }
251
+
252
+ .mm-controls-shell > div,
253
+ .mm-controls-shell > div > div,
254
+ .mm-controls-shell .form,
255
+ .mm-controls-shell .form *,
256
+ .mm-controls-shell [role="listbox"],
257
+ .mm-controls-shell ul {
258
+ overflow: visible !important;
259
+ }
260
+
261
+ .mm-select {
262
+ position: relative;
263
+ z-index: 21;
264
+ }
265
+
266
+ .mm-controls-shell label,
267
+ .mm-controls-shell label span {
268
+ color: var(--mm-ink) !important;
269
+ }
270
+
271
+ .mm-controls-shell p {
272
+ color: var(--mm-muted) !important;
273
+ }
274
+
275
+ .mm-select > div,
276
+ .mm-select .wrap,
277
+ .mm-select input,
278
+ .mm-select button,
279
+ .mm-select [role="combobox"] {
280
+ background: var(--mm-surface-soft) !important;
281
+ border-color: var(--mm-line) !important;
282
+ color: var(--mm-ink) !important;
283
+ border-radius: 14px !important;
284
+ }
285
+
286
+ .mm-controls-shell [role="listbox"],
287
+ .mm-controls-shell ul {
288
+ background: var(--mm-surface) !important;
289
+ border: 1px solid var(--mm-line) !important;
290
+ color: var(--mm-ink) !important;
291
+ z-index: 80 !important;
292
+ }
293
+
294
+ .mm-controls-shell [role="option"] {
295
+ color: var(--mm-ink) !important;
296
+ }
297
+
298
+ .mm-controls-shell [role="option"]:hover,
299
+ .mm-controls-shell [role="option"][aria-selected="true"] {
300
+ background: var(--mm-accent-soft) !important;
301
+ }
302
+
303
+ .mm-compare-panel {
304
+ margin-top: 1rem;
305
+ padding: 1rem;
306
+ border: 1px solid var(--mm-line);
307
+ border-radius: 14px;
308
+ background: var(--mm-surface);
309
+ box-shadow: var(--mm-shadow);
310
+ }
311
+
312
+ .mm-panel-head {
313
+ display: flex;
314
+ justify-content: space-between;
315
+ align-items: flex-start;
316
+ gap: 1rem;
317
+ margin-bottom: 1rem;
318
+ }
319
+
320
+ .mm-panel-head h3 {
321
+ margin: 0.15rem 0 0.4rem;
322
+ color: var(--mm-ink);
323
+ font-size: 1.35rem;
324
+ font-weight: 700;
325
+ line-height: 1.15;
326
+ }
327
+
328
+ .mm-panel-head p {
329
+ margin: 0;
330
+ color: var(--mm-ink-soft);
331
+ line-height: 1.7;
332
+ }
333
+
334
+ .mm-panel-head strong {
335
+ color: var(--mm-ink);
336
+ }
337
+
338
+ .mm-chip-row {
339
+ display: flex;
340
+ flex-wrap: wrap;
341
+ gap: 0.5rem;
342
+ }
343
+
344
+ .mm-chip {
345
+ display: inline-flex;
346
+ align-items: center;
347
+ padding: 0.4rem 0.72rem;
348
+ border: 1px solid var(--mm-line);
349
+ border-radius: 999px;
350
+ background: var(--mm-surface-soft);
351
+ color: var(--mm-ink-soft);
352
+ font-size: 0.84rem;
353
+ font-weight: 700;
354
+ }
355
+
356
+ .mm-compare-grid {
357
+ display: grid;
358
+ grid-template-columns: repeat(2, minmax(0, 1fr));
359
+ gap: 1rem;
360
+ }
361
+
362
+ .mm-compare-card {
363
+ border-top: 2px solid var(--mm-card-accent, var(--mm-accent));
364
+ }
365
+
366
+ .mm-compare-head {
367
+ padding: 0.9rem 1rem 0.75rem;
368
+ }
369
+
370
+ .mm-compare-desc {
371
+ margin: 0.3rem 0 0;
372
+ color: var(--mm-ink-soft);
373
+ font-size: 0.88rem;
374
+ line-height: 1.5;
375
+ }
376
+
377
+ .mm-compare-card-10m {
378
+ --mm-card-accent: #9a6237;
379
+ }
380
+
381
+ .mm-compare-card-base-e {
382
+ --mm-card-accent: #2f6a73;
383
+ }
384
+
385
+ .mm-compare-card-100m {
386
+ --mm-card-accent: #7a4c8f;
387
+ }
388
+
389
+ .mm-compare-card-fullbody-base {
390
+ --mm-card-accent: #c13a5b;
391
+ }
392
+
393
+ .mm-bibtex {
394
+ margin: 0;
395
+ padding: 1rem 1.2rem;
396
+ border: 1px solid var(--mm-line);
397
+ border-radius: 14px;
398
+ background: var(--mm-surface);
399
+ box-shadow: var(--mm-shadow);
400
+ color: var(--mm-ink);
401
+ font-family: "SFMono-Regular", ui-monospace, Menlo, Consolas, monospace;
402
+ font-size: 0.85rem;
403
+ line-height: 1.6;
404
+ overflow-x: auto;
405
+ white-space: pre;
406
+ }
407
+
408
+ .mm-bibtex code {
409
+ background: transparent;
410
+ color: inherit;
411
+ font: inherit;
412
+ }
413
+
414
+ .mm-compare-video {
415
+ overflow: hidden;
416
+ background: #0f172a;
417
+ aspect-ratio: 16 / 10;
418
+ }
419
+
420
+ .mm-compare-video video {
421
+ display: block;
422
+ width: 100%;
423
+ height: 100%;
424
+ object-fit: cover;
425
+ background: #0f172a;
426
+ }
427
+
428
+ .mm-link-strip {
429
+ display: grid;
430
+ grid-template-columns: repeat(4, minmax(0, 1fr));
431
+ gap: 1rem;
432
+ margin-top: 0.75rem;
433
+ }
434
+
435
+ .mm-link-card {
436
+ display: flex;
437
+ flex-direction: column;
438
+ gap: 0.32rem;
439
+ min-height: 88px;
440
+ padding: 1rem;
441
+ text-decoration: none;
442
+ transition: border-color 0.18s ease;
443
+ }
444
+
445
+ .mm-link-card:hover {
446
+ border-color: var(--mm-accent);
447
+ background: var(--mm-surface-soft);
448
+ }
449
+
450
+ .mm-link-title {
451
+ color: var(--mm-ink);
452
+ font-size: 1rem;
453
+ font-weight: 700;
454
+ }
455
+
456
+ .mm-link-note {
457
+ color: var(--mm-muted);
458
+ font-size: 0.9rem;
459
+ line-height: 1.5;
460
+ }
461
+
462
+ @media (max-width: 1100px) {
463
+ .mm-video-grid,
464
+ .mm-compare-grid,
465
+ .mm-link-strip {
466
+ grid-template-columns: repeat(2, minmax(0, 1fr));
467
+ }
468
+ }
469
+
470
+ @media (max-width: 820px) {
471
+ .gradio-container {
472
+ padding: 18px 16px 48px !important;
473
+ }
474
+
475
+ .mm-hero,
476
+ .mm-compare-panel {
477
+ padding-left: 1rem;
478
+ padding-right: 1rem;
479
+ }
480
+
481
+ .mm-hero h1 {
482
+ max-width: none;
483
+ font-size: clamp(2rem, 9vw, 2.7rem);
484
+ }
485
+
486
+ .mm-panel-head {
487
+ flex-direction: column;
488
+ }
489
+
490
+ .mm-video-grid,
491
+ .mm-compare-grid,
492
+ .mm-link-strip {
493
+ grid-template-columns: 1fr;
494
+ }
495
+ }
uv.lock ADDED
The diff for this file is too large to render. See raw diff
 
videos/blog/airkick.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a27acde6b00ccfbfae8d7602893a3341e6ca36e308acba375711dead79c08c5d
3
+ size 3460884
videos/blog/backwards_walking.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:60129095a87ceb13fe2add7e0bc89aba612438c7d97ef98c150adf7637effa67
3
+ size 2560916
videos/blog/bimanual_out.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2e42e498752b7447a8bb2c36b27a599aeefe1aae81f8396927c5a763abde59cc
3
+ size 934466
videos/blog/dancing.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8591b0e5c25365d6bf03951fd5687c5e052ef9b2ede1418c9256950cdc7de4b2
3
+ size 3120012
videos/blog/drinking_water.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:03b22170a0b13c4bca46510daa186f9a47598a6f0cd2a37741a0e68c334c864b
3
+ size 1100096
videos/blog/jumpingjack.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:85cc7bf7b1825a9670c61f80b5cfed51930f54ec37e9a3a04c6a298238679cd6
3
+ size 1347985
videos/blog/lifting_box.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:80e54cf75d9412c2f38efe97e8c2fd78c186753535618911c409c958997c503f
3
+ size 1337550
videos/blog/walking_running.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:870b36fac402d51ead7c67d0545682e46c60dc1378914a403b283eb1197c3925
3
+ size 2952738
videos/blog/walking_turning.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c66b5d46a858cc96d7a3523f04f0fec7bb7508e609d950c9f6e4451af24c7c52
3
+ size 3787918
videos/blog/waving.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f0dd216ef826103131053648b4de5c476bfb9e25a37398c5eb9ae1f6105330cf
3
+ size 1226849
videos/demo/mm-100M-s1/KIT_10_RightTurn02_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3f96546a4106085df017166499dd798453fe751b3706e61d69b08bb28ade226c
3
+ size 3026274
videos/demo/mm-100M-s1/KIT_10_WalkingStraightBackwards07_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c26514eed5b4d2ae56fcd1a9bb15ee2f5c7a6cbfddc5bd114d4ca61c2cca8a42
3
+ size 3045427
videos/demo/mm-100M-s1/KIT_11_LeftTurn05_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:43da7a6f92a6958e0051dd0ae5ddb0edbe0e1173840b525b4aa936ac9cb9a3d0
3
+ size 3062648
videos/demo/mm-100M-s1/KIT_11_WalkInCounterClockwiseCircle02_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0596c8dcb4b68c159fe5eec6c923df74fcab0cf8d74df218c09c9b144875d7b7
3
+ size 3264482
videos/demo/mm-100M-s1/KIT_11_WalkingStraightBackwards09_1_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cf1d62d3e16d31f03a09edfa7b45b3794c7a1c89aee12b2a03075da870e8fcd4
3
+ size 2957206
videos/demo/mm-100M-s1/KIT_11_WalkingStraightForwards05_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:17fc52fbb099d1ffd11e39ffcb368457a9e65fe58ec8801fa1892bbd7069b06b
3
+ size 2997842
videos/demo/mm-100M-s1/KIT_12_LeftTurn03_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:046ec31551c17792ea08ef63e86e12efe1d29972735dd1833738013801bc6657
3
+ size 2842931
videos/demo/mm-100M-s1/KIT_12_WalkInClockwiseCircle11_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:782f83ae47953a9c5c8f999f635f08ebb9a05a26d41d803164563d1f65b193cb
3
+ size 3632339
videos/demo/mm-100M-s1/KIT_12_WalkingStraightBackwards05_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:52971e537d20fc4927dc97b73d25dbeef81f25faf5d453abd50814998616a181
3
+ size 2514766
videos/demo/mm-100M-s1/KIT_167_walking_medium03_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:11f023006b4dd415518fbcf5307902b7f59142b4222ba3bfa5b8436316888b91
3
+ size 3060290
videos/demo/mm-100M-s1/KIT_314_walking_run09_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:088e87651aeb26ad8cad2b32ff325595d432b923fb99475b7bf48c517d5e5d89
3
+ size 3134867
videos/demo/mm-100M-s1/KIT_314_walking_slow03_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b7591665737e1c9caac0f32f3252733f4007db557df143b11bcf70a5dff433ac
3
+ size 2277236
videos/demo/mm-100M-s1/KIT_348_turn_right06_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6e6590c96393221f42d32bb5b8596a6b534a9a42ad62678dfceb2c0bf698c819
3
+ size 2964701
videos/demo/mm-100M-s1/KIT_359_turn_left05_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:eedcb310052bc69f0d50a4eeca2d256bf942d97e5e1c939b3b38f7ec28f2d759
3
+ size 3764136
videos/demo/mm-100M-s1/KIT_3_turn_right04_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8c5993e5ad38376efb94341b3a428b116484a576388b8f98f302b4f136dbe482
3
+ size 3688560
videos/demo/mm-100M-s1/KIT_424_turn_right02_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4d7e05dcc5a0b13c22de740cbe472b6f1889ce5543fcc41bf31d72d9733a77c7
3
+ size 3325110
videos/demo/mm-100M-s1/KIT_424_walking_fast10_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c41b2b8a8ca6f9e4455ce7fa18731e9b543b2ee520f87c0d19435bb18433839d
3
+ size 3003597
videos/demo/mm-100M-s1/KIT_4_WalkInClockwiseCircle04_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:01fceec9de75976441a36bb138c32b44eb55d083b5aab114c3335fc1f5f9ef54
3
+ size 3730520
videos/demo/mm-100M-s1/KIT_4_WalkingStraightBackwards01_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cf93f62bf7b2d04a90e1c2fac48e808dce13bc90555ffdb9f4c11832ccc991d0
3
+ size 2829571
videos/demo/mm-100M-s1/KIT_6_WalkInCounterClockwiseCircle04_1_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:049830d8c4bc3a6bd840a2cc8c920ea639f2ccdc5400adc1ea1c7ea75f5020ff
3
+ size 3156429
videos/demo/mm-100M-s1/KIT_6_WalkInCounterClockwiseCircle06_1_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d635a12fc3a573ee26d33468d07a614de9a3315be637718ecb2347a9f4dc6633
3
+ size 3404021
videos/demo/mm-100M-s1/KIT_6_WalkingStraightBackwards04_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:33aab6eeb0bcd6a99c492491cd8f79eb390034acfb8559e6d36399c019354a66
3
+ size 2737747
videos/demo/mm-100M-s1/KIT_7_LeftTurn06_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5b9e9d5f05e4e214c1c8d867e32a8c90564b89a1c10582192370c540c3444a2b
3
+ size 2940361
videos/demo/mm-100M-s1/KIT_7_WalkingStraightBackwards04_poses/eval_MyoFullBody.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:107011b2ff8926574be8cdcfa2b2ba6107d27f6bf65f1e90965f35f3a3fdcfd2
3
+ size 2773446