π₯ COF Motion
BVH and VRMA clips are only half a pipeline β this node is the other half's postman
- cof
- paths
- labels
- count
What it hands you
Motion clips. A .cof can carry them, and COF Motion exports the preset's clips to ComfyUI/input/cof/cof-<file-stem>/, then returns their paths. Formats in play are skeleton animation files - BVH, VRMA - and short videos (mp4, webm).
It's the same code path as COF 3D, with a different destination folder. Same pick semantics, same all default, same "returns strings, writes files" behaviour. If you've read the 3D node, this one is the sequel with the folder name changed.
Be honest about the state of motion in ComfyUI
Here's the thing nobody says in the README: a BVH file is not a video. It's joint rotations over time against a skeleton hierarchy. To turn one into pixels you need something that reads it, a rigged mesh to apply it to, a retarget step if the skeleton conventions don't match, and a renderer. That chain is thin in ComfyUI - most of the ecosystem's motion work lives upstream of this in Blender or Mixamo, or in the motion-capture direction (video in, skeleton out) rather than the playback direction.
What ComfyUI is good at is the other end: the mp4/webm clips. Those are just video, and any video-loading node can take a path. That's the honest split - short video clips drop into existing image-to-video and video-edit graphs without ceremony; skeleton clips are for people who already have a rig-and-animate pipeline and are not going to have one fall out of this node.
Which raises the real question: why ship them in a character file at all? Because the motion belongs to the character. The walk cycle, the idle, the specific gesture - that's authored per character, and if it's not in the bundle it's in a folder with a name like anims_v2_FINAL. Same argument as every other node in this pack; this one just has the least mature consumer end.
How it works, mechanically
The reader walks the preset's motion variants and collects clips, keeping labels in a readable variant Β· filename form. Anything not on the extractor whitelist is listed but not extracted, with the label saying so in parentheses - that's a deliberate honesty feature rather than a silent drop.
Only files that can actually be extracted get a path. Then:
ComfyUI/input/cof/cof-<cof-file-stem>/
The cof- prefix and per-file subfolder keep two characters from overwriting each other's idle.bvh.
Inputs and outputs
Required: cof, pick (all, plus item_001β¦item_064, labelled per file in the UI).
paths- newline-separated absolute paths, one per exported clip.labels- one line per clip the preset has, or(this preset has no motion clip).count- how many the preset has, not how many you exported.count: 3with one path inpathsmeans you picked one of three.
Because paths is a STRING with newlines, one-string-per-node consumers are a mild annoyance: a loader that expects a single path will get a multi-line string if you exported all. Pick one item, or split the string.
Install
No extra packages, nothing for this node specifically. The pack's pyproject.toml declares an empty dependency list.
cd ComfyUI/custom_nodes
git clone https://github.com/yannsouetre/ComfyUI-COF
mkdir -p ComfyUI/models/cof
cp your-character.cof ComfyUI/models/cof/
Restart, press R for new files. The preview workflow includes a COF Motion node with a Preview Any on the paths - the pack's own demo stops at "look, a path", which tells you something about how far the consumer side is from being settled.
Whatever you use downstream is a separate install: a video loader for the mp4s, and for the skeleton clips a rig-and-render stack that ComfyUI doesn't provide out of the box.
Common issues
paths empty, count 0. No motion variants on this preset. Normal, not an error.
A clip appears in labels but has no path. It's a format the extractor won't touch. The label says so in parentheses - read labels, not just paths.
Your video loader can't find the file. It's in input/cof/cof-<stem>/, not at the top of input/. Some loaders only list one level deep; either move the file or use a loader that takes a full path string.
Multiple paths into a single-path input. Export one item instead of all - the widget makes this easy and the alternative is parsing strings in a graph that has no string splitting worth the name.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| cof | COF | β | |
| pick | COMBO | all | the preset's files by name; all = every one |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| paths | STRING | β |
| labels | STRING | β |
| count | INT | β |