Nodes/AnimoFlow/Outlier Fix (AnimoFlow)
ComfyUI Node

Outlier Fix (AnimoFlow)

Cleaning the random joint explosions out of your generated motion

By AnimoFlow·Created 2 months ago·Updated about a month ago· 1
Outlier Fix (AnimoFlow)
  • bvh_b64
  • bvh_b64
enabledtrue
k5
h3.5
max_spike_len5

Every so often a text-to-motion run comes back with a joint that briefly teleports - an elbow at the ceiling for a frame or two, a wrist that spikes to the side and snaps back. Diffusion denoising occasionally invents a pose that's anatomically impossible, and it shows up as a sharp positional outlier in the BVH. AnimoFlow_OutlierFix is the node that finds those spikes and removes them. BVH in, BVH out, and it's on by default because it's genuinely safe to run on everything.

How it works, from the source: it flags frames where a joint's position deviates enough from its neighbors to count as an outlier (a thresholded median-style detector - the k and h parameters control the window and the sensitivity), and then fixes each contiguous run of bad frames that's short enough to be a spike (up to max_spike_len) by slerping between the good anchor frames on either side. Slerp means spherical interpolation on quaternions, so the fix stays on the manifold of valid rotations rather than blending raw numbers that would leave the skeleton distorted. Short spike, clean splice; longer genuine motion changes are left alone.

The settings

  • enabled - default true. Unlike AnimoFlow_FootSkatingFix, this one's on out of the box. If you're debugging a weird pose, this is the first suspect to toggle off - it does change the motion, however subtly.
  • k - 1–20, default 5. The window of neighboring frames used to judge whether a frame is an outlier. Larger = a smoother baseline to compare against, at the cost of responsiveness to real fast motion.
  • h - 1–10, default 3.5. The sensitivity threshold - how far a joint can deviate before it's flagged as a spike. Lower h = more aggressive filtering.
  • max_spike_len - 1–20, default 5. The longest spike the fix will touch. Anything longer is treated as real motion, not noise, and left alone. This is the parameter that stops the filter from eating a legitimate quick movement like a punch.

Where it sits

It takes an ANIMOFLOW_BVH and returns an ANIMOFLOW_BVH, so it drops between AnimoFlow_IK and AnimoFlow_Rig, ideally before AnimoFlow_FootSkatingFix (fix the position spikes first, then the contact/floor cleanup). Same socket type in and out means you can add it to a hand-built graph without touching anything else.

The honest take

Like the other BVH filters in the pack, this is a native node - no container, no weights, runs in the ComfyUI process off motion_utils/outlier_fix.py with just numpy/scipy. It's cheap, deterministic, and safe, which is exactly why it ships enabled. Where people get tripped up is rarely the node itself; it's the assumption that a pose problem is an outlier problem. If you're seeing a persistent distorted pose rather than a one-frame spike, max_spike_len and h won't save you - that's a generation failure, re-run with a different seed. And if the node doesn't import, it's the same old story: the pack's requirements.txt needs to be installed in ComfyUI's Python environment.

CategoryAnimoFlow/PostProcess

Inputs (5)

NameTypeDefaultDescription
bvh_b64ANIMOFLOW_BVH
enabledBOOLEANtrue
koptINT51–20
hoptFLOAT3.51–10
max_spike_lenoptINT51–20

Outputs (1)

NameTypeDescription
bvh_b64ANIMOFLOW_BVH