FTH 3 · Whole body|INEMA.CLUB-PRO

Lesson 2 · 15 min

Human motion as data

2026 whole-body policies learn from hours of human motion. Before using that data, you need to know how to read it and whether you are allowed to use it. In this lesson you open a BVH clip, count frames, fps and joints, write a clip of your own, and understand why the course does not redistribute any public dataset.

Start the lesson
Person in a black motion capture suit with reflective markers in a boxing pose, surrounded by cameras in a dark studio.

In this lesson you will

  1. 1Where human motion comes from: mocap, video and VR
  2. 2The BVH format inside: a skeleton and one line per frame
  3. 3AMASS, LAFAN1 and the license question
  4. 4How to catch a truncated clip before it ruins the retargeting

Goal: read a motion capture clip (BVH) and report frames, fps and joints, knowing where the data comes from and under what license.

01From a person's movement to a file

Click each block.

Click each block of the diagram to see what it does.

Motion data is training input: license and integrity come before quantity.

02The datasets you will run into

Click each one.

1. AMASS

A collection of many captures converted to the same parametric body (SMPL-X). It is the most common input for GMR and for several motion tracking works.

Requires registration on the site. The terms for an open course were not checked: read them before using it and before publishing anything derived from it.

03Download only the GMR test clip and read it

The GMR repository has 1.2 GB in the assets folder, because of the robot meshes. The sparse-checkout downloads only the clip's folder, 2.9 MB (measured on 10/19/2026, commit bb1bbe4). ler_clipe.py uses no extra library: it reads the BVH text.

Terminal · GMR clip
F=${FTH:-$HOME/fth}; cd $F
[ -d GMR ] || git clone -q --filter=blob:none --sparse https://github.com/YanjieZe/GMR
cd GMR && git sparse-checkout set assets/xsens_bvh_test
git checkout -q bb1bbe4 && git log -1 --format='GMR %h (%ad)' --date=short
cd $F/corpo-inteiro && . $F/.venv/bin/activate
python3 kit/ler_clipe.py $F/GMR/assets/xsens_bvh_test/251021_04_boxing_120Hz_cm_3DsMax.bvh; echo "saída: $?"
BVH excerpt (header of the GMR test clip)
HIERARCHY
ROOT Hips
{
 OFFSET 0.000000 0.000000 0.000000
 CHANNELS 6 Xposition Yposition Zposition Yrotation Xrotation Zrotation
 JOINT Chest
 {
  OFFSET 0.000000 10.149404 -1.127712
  CHANNELS 3 Yrotation Xrotation Zrotation
(…)
MOTION
Frames: 4249
Frame Time: 0.008333
Example from the repository
GMR bb1bbe4 (2026-04-02)
arquivo: 251021_04_boxing_120Hz_cm_3DsMax.bvh
raiz: Hips · juntas: 23 · pontas (End Site): 5 · canais por quadro: 72
ordem de rotação: Yrotation Xrotation Zrotation · unidade provável: cm (maior OFFSET 43.3)
quadros: 4249 · fps: 120 · duração: 35.4 s
linhas de movimento conferidas: 4249/4249
saída: 0

23 joints with 3 rotation channels, plus 3 extra position channels on the root: 72 numbers per frame. Frame Time of 0.008333 s = 120 frames per second.

04A BVH of your own, made from scratch

Five joints (hips, spine, head, right arm and right forearm), 60 frames at 30 Hz: the arm rises in 0.5 s and the forearm waves.

Terminal · generate and read aceno.bvh
F=${FTH:-$HOME/fth}; cd $F/corpo-inteiro && . $F/.venv/bin/activate
python3 kit/bvh_minimo.py && python3 kit/ler_clipe.py $F/movimentos/aceno.bvh; echo "saída: $?"
Example from the repository
gravado: ~/fth/movimentos/aceno.bvh (60 quadros a 30 Hz)
arquivo: aceno.bvh
raiz: Hips · juntas: 5 · pontas (End Site): 2 · canais por quadro: 18
ordem de rotação: Zrotation Xrotation Yrotation · unidade provável: cm (maior OFFSET 30.0)
quadros: 60 · fps: 30 · duração: 2.0 s
linhas de movimento conferidas: 60/60
saída: 0

3 channels per joint + 3 for the root position = 18. The same reading works for any BVH.

05Practice

Read it, check it, and decide whether you can use it.

E1 · Read the GMR clip

5 min

Run the clip block and note the frames, fps and duration.

Done when: python3 kit/ler_clipe.py ~/fth/GMR/assets/xsens_bvh_test/251021_04_boxing_120Hz_cm_3DsMax.bvh | tail -1 → linhas de movimento conferidas: 4249/4249.

E2 · Your slower wave

5 min

Generate the wave with 90 frames at 30 Hz and read it again.

Done when: python3 kit/bvh_minimo.py --quadros 90 && python3 kit/ler_clipe.py ~/fth/movimentos/aceno.bvh | grep quadros → quadros: 90 · fps: 30 · duração: 3.0 s.

E3 · License sheet

10 min

For a clip you want to use (AMASS, LAFAN1 or another), write three lines in ~/fth/movimentos/licenca.md: Fonte, Licença (with the link) and Pode redistribuir.

Done when: grep -c -E "^(Fonte|Licença|Pode redistribuir):" ~/fth/movimentos/licenca.md → 3.

06Lesson quiz

The explanation appears after your answer.

Question 1 of 3

The header says Frames: 4249 and Frame Time: 0.008333. How long is the clip?skill

07In three sentences

FormatBVH = skeleton + one frame per line; frames, fps and channels come from the text.
LicenseWithout clear terms, don't redistribute: use your own data or data that ships with a license.
IntegrityCheck frames × lines before any retargeting.

Going further

Previous lessonNext lesson