Kimodo Text to Pose
Type a sentence, get a .npz of human motion
- model
- npz_path
- result
This is the payoff node. A prompt goes in, a compressed .npz of 3D joint motion comes out - 30fps, 77 joints on the SOMA skeleton, plus per-joint rotation matrices. Wire KimodoLoader's model in, type "a person walks forward and then waves", hit run.
What it is not: a video generator, or a rig. There's no mesh here and no render. You get numbers that describe a moving skeleton, and something downstream has to drive a body with them.
How the motion gets made
Under the hood the node calls the Kimodo model's __call__ with a list of prompts and a frame count per prompt, and Kimodo runs its own diffusion loop - that's where the diffusion_steps number goes. Frame count is derived, not guessed: the model's fps is 30, and the node rounds duration_sec × 30. So duration_sec 6.0 gives you 180 frames of motion.
Before sampling it seeds python, numpy and torch from your seed, which is why a fixed seed gives you reproducible output instead of a coin flip. And ComfyUI's memory manager loads the model onto the GPU first, which is the thing that stops the device-mismatch crash the pack was rewritten to fix.
There's a nice detail buried in the source: the node wraps the model's internal progress loop with its own interrupt check, so the Cancel button kills a run partway through instead of appearing dead until generation finishes. Diffusion over 100 steps at 30fps of motion takes a while, so you'll appreciate that.
One upstream quirk worth knowing: models with g1 in the resolved name skip post-processing entirely. If a G1 variant produces visibly rawer motion than another variant, that's why.
The inputs you'll actually touch
Required: model (from KimodoLoader), prompt (multiline, hard-capped at 2000 characters - over that it raises, empty raises), and seed.
Then the optional ones, in the order you'll care about them.
duration_secdefaults to 6 and maxes at 10. That ceiling is upstream's, not the pack's: 10 seconds is the most Kimodo will generate for a single prompt. Want a longer clip? That's whatmotion_promptsis for.diffusion_stepsdefaults to 100. This is your quality-versus-time dial and it's the honest one - sampling steps, nothing exotic.num_samples(1–8) generates several candidates. Note that only the first is written to the file; the rest exist during the run.cfg_type(separated,regular,nocfg) withcfg_weight_aandcfg_weight_bat 2.0 each. Leave these alone until you have a reason.num_transition_frames(default 30) is how long the model takes to blend between prompt segments. It only matters once you use segments.motion_promptsis the interesting one: a JSON list of{"text": "...", "duration_sec": 2.0}segments. Feed it two or more valid entries and it overrides your singleprompt- Kimodo composes a multi-segment performance with transitions between them. Malformed JSON raises loudly; entries that are individually broken get dropped rather than crashing the run.prev_motion_npzis chain mode. Give it the bare filename of a previous motion stored in ComfyUI'sinputdirectory, and the new clip is generated conditioned on where the old one ended - the motion equivalent of a first-frame constraint. The transition frames get dropped and the two clips are merged into one output.motion_constraintstakes hand-authored timeline constraints as JSON. If you're not generating that JSON from a UI, you're not going to want to write it by hand.
Outputs
npz_path is a real filesystem path: the file lands in ComfyUI's output directory as kimodo_pose_<timestamp>_<seed>.npz, and the node logs the frame count and motion duration when it's done. result is a KIMODO_RESULT - a metadata dict carrying motion_shape, fps, the prompt, the seed and how many seconds inference took. Useful if you're logging runs; it is not what you feed the next node.
The .npz is the thing you carry forward, into whatever retargets motion onto a character.
Install
Same pack as everything else here:
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/JayDataEngineer/melite-kimodo-nodes.git
cd melite-kimodo-nodes
pip install -r requirements.txt
Restart, then load the model from KimodoLoader before you run this. The single most common failure in the whole pack belongs to that loader - if your run dies with No module named 'kimodo', it's a missing dependency, not a bad prompt.
Watch out for
Prompts over 2000 characters raise rather than truncate - that's deliberate, but it bites people pasting a whole shot description. Wire a batch of anything into duration_sec and remember the 10-second ceiling, because the clamp isn't where you'd look for it. And a 6-second clip at 100 steps is not fast on a card that's also holding a 17GB text encoder. Budget the run, not the prompt.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| model | KIMODO_MODEL | — | |
| prompt | STRING | — | |
| seed | INT | 420–4294967295 | — |
| duration_secopt | FLOAT | 6.000.1–10 | — |
| diffusion_stepsopt | INT | 1001–1000 | — |
| num_samplesopt | INT | 11–8 | — |
| num_transition_framesopt | INT | 300–300 | — |
| cfg_typeopt | COMBO | separated | 3 options: separated, regular, nocfg |
| cfg_weight_aopt | FLOAT | 2.000–20 | — |
| cfg_weight_bopt | FLOAT | 2.000–20 | — |
| prev_motion_npzopt | STRING | — | |
| motion_constraintsopt | STRING | — | |
| motion_promptsopt | STRING | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| npz_path | STRING | — |
| result | KIMODO_RESULT | — |