> For the complete documentation index, see [llms.txt](https://animotive.gitbook.io/animotive-kimodo/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://animotive.gitbook.io/animotive-kimodo/advanced/file-formats.md).

# File Formats (BVH / Constraints JSON)

Reference for the two file formats that move through the Animotive Kimodo pipeline in the current shipping product: the **constraints JSON** the plugin writes alongside every generation request, and the **BVH** the solver returns.

***

## Constraints JSON — Animotive Kimodo request

The constraints JSON is the document the plugin writes to `Saved/Kimodo/` (or the configured **Host Export Dir** for the Local Docker backend) every time you press **Generate with Kimodo**. It is the request body sent to the local Docker CLI (via `--constraints`) and to the FastAPI server for Self-Hosted / Animotive Kimodo (hosted). It captures the prompt text, the section timings, generation hyperparameters, and the per-frame samples from the Kimodo Constraints track plus (when present) the Control Rig keyframes.

### Schema

| Field                  | Default | Meaning                                                                                                                                                  |
| ---------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `model`                | n/a     | Kimodo model name. Docker uses `Kimodo-SOMA-RP-v1`; Self-Hosted (HTTP) uses `kimodo-soma-rp`. Switching backends typically requires retyping this field. |
| `meta.texts[]`         | n/a     | Array of prompt strings, one entry per Animotive Kimodo section, in section order.                                                                       |
| `meta.durations[]`     | n/a     | Array of section durations in seconds. Length matches `texts`.                                                                                           |
| `meta.num_samples`     | `1`     | Number of samples Kimodo should generate.                                                                                                                |
| `meta.diffusion_steps` | `100`   | Diffusion solver step count. Raise for quality, lower for speed.                                                                                         |
| `meta.seed`            | `42`    | RNG seed for reproducibility.                                                                                                                            |
| `constraints[]`        | `[]`    | Per-frame sample entries from the Kimodo Constraints track and (optionally) the Control Rig. See below.                                                  |
| `bvh_standard_tpose`   | `true`  | Asks Kimodo to emit BVH in the standard SOMA T-pose. Leave on.                                                                                           |

### `constraints[]` entries

Each entry pins one channel at one frame. Channel types match the six rows on the Kimodo Constraints track:

* `fullbody`
* `2d-root`
* `left-hand`
* `right-hand`
* `left-foot`
* `right-foot`

Each entry carries:

* `type` — one of the channel tokens above.
* `frame` — integer frame index (at 30 fps).
* `pose` — the pose payload at that frame. For full-body entries this carries the complete SOMA77 pose; for limb / root entries it carries the relevant joint subset.

### Example

```json
{
    "model": "Kimodo-SOMA-RP-v1",
    "meta": {
        "texts": ["a person walks forward", "stops and waves"],
        "durations": [1.5, 1.0],
        "num_samples": 1,
        "diffusion_steps": 100,
        "seed": 42
    },
    "constraints": [
        {
            "type": "fullbody",
            "frame": 0,
            "pose": { "rotvecs": "…(77 joints)", "root_pos": [0.0, 0.95, 0.0] }
        },
        {
            "type": "left-foot",
            "frame": 22,
            "pose": { "position": [-0.10, 0.00, 0.30], "planted": true }
        },
        {
            "type": "2d-root",
            "frame": 45,
            "pose": { "xy": [0.20, 0.80], "facing_deg": 15.0 }
        }
    ],
    "bvh_standard_tpose": true
}
```

The shape of `pose` varies by channel — full-body carries the complete pose, limb channels carry an end-effector position with optional `planted` flag, and `2d-root` carries the floor-plane root pin. You should rarely need to author one by hand, but the format is plain JSON and is safe to inspect or diff between runs.

***

## BVH — Kimodo solver output

When the solver finishes, it returns a standard Biovision Hierarchy (`.bvh`) file. The plugin's BVH import factory consumes it and routes it through the import + retarget pipeline. BVH is always emitted in a **SOMA T-pose** — Kimodo does not rebind onto your character. The IK Retargeter on the Animotive Kimodo track is what maps that SOMA-skeleton animation onto your MetaHuman or other body rig.

### HIERARCHY block

* **Joint names match SOMA77 names** (`Hips`, `Spine1`, `Spine2`, `Chest`, `Neck1`, `Neck2`, `Head`, …). Joint order in the file matches the SOMA77 index order.
* **`OFFSET` is in centimetres**, expressed in the SOMA77 basis.
* **Root channels:** `Xposition Yposition Zposition Zrotation Xrotation Yrotation` — position followed by Z-X-Y Euler rotation.
* **Non-root channels:** three rotation channels per joint, same order as the root's rotation channels.
* **End Site blocks** appear on chain terminators (finger tips, toe ends, head end). The parser consumes them as offsets but does not emit them as joints.

### MOTION block

* `Frames: N` — total sample count.
* `Frame Time: dt` — seconds per frame; `0.033333` for 30 fps.
* Each subsequent row is `N_channels` floats, space-separated, in the order declared in `HIERARCHY`.
* Root translation is in **centimetres**. Rotations are in **degrees** (standard BVH); the parser converts to radians.

### Example

```bvh
HIERARCHY
ROOT Hips
{
    OFFSET 0.00 0.00 0.00
    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
    JOINT Spine1
    {
        OFFSET 0.00 10.50 0.00
        CHANNELS 3 Zrotation Xrotation Yrotation
        ...
    }
}
MOTION
Frames: 2
Frame Time: 0.033333
0.000 95.20 0.000  0.00  0.00  0.00   0.00  0.00  0.00   ...
0.012 95.18 0.004  0.30 -0.10  0.05   0.40 -0.05  0.02   ...
```

The parser tolerates BVH variants from different Kimodo builds: tabbed vs space-indented hierarchies, trailing `\r` on Windows exports, and historical Z-X-Y / Y-X-Z channel-order drift between solver versions. The file converges on a SOMA T-pose skeleton at the parser boundary, and the IK Retargeter on the track does the actual rebinding onto the character.

***

## Where the files land

* **Local (Docker) backend.** The constraints JSON is written to the **Host Export Dir** configured under **Project Settings → Plugins → Kimodo Exporter → Kimodo Docker**. The host directory is bind-mounted to the container at **Container Export Dir**, so the solver writes the returned BVH back into the same host folder.
* **Self-Hosted (HTTP) backend.** The constraints JSON is written to `<Project>/Saved/Kimodo/` before being POSTed to the FastAPI server. The returned BVH is downloaded into the same folder.
* **Imported `UAnimSequence` assets.** Once the BVH is parsed and retargeted onto the character, the resulting animation asset is saved under `/Game/Kimodo/Generated/<MeshName>/Sequences/`.

Every generation also leaves a row on the **Animotive Kimodo Monitor** panel (Tools → Animotive Kimodo → Monitor) that links lifecycle state, warnings, and timing to the specific request — useful when you need to correlate an on-disk artefact with the run that produced it.

## See also

* [SOMA77 Skeleton](/animotive-kimodo/advanced/skeleton-and-rotation.md)
* [Remote API Reference](/animotive-kimodo/advanced/remote-api.md)
* NVIDIA Kimodo: [skeleton key concept](https://research.nvidia.com/labs/sil/projects/kimodo/docs/key_concepts/skeleton.html)
