Extensions/comfyui-teskors-utils
ComfyUI Extension

comfyui-teskors-utils

Smooth and stabilise OpenPose in ComfyUI: removes pose jitter, hand flicker and dropped keypoints before ControlNet

By teskor-hub·Created 7 months ago·Updated 25 days ago· 4
teskor-hub/comfyui-teskors-utils
Nodes5
On cloudLocal install
CategoryTS Utils/Video, TS Utils/Pose
Stars4
Updated25 days ago
Readme

Teskor's Utils

Stop OpenPose from shaking.

Raw OpenPose output jitters. Keypoints vibrate when the subject is still, joints drop out for a frame and pop back, and a limb occasionally snaps somewhere impossible. Feed that into ControlNet and the generated video inherits every bit of it.

TS Pose Data Smoother cleans the pose sequence before it ever reaches your generation: temporal smoothing, gap filling, outlier rejection and subject tracking. Built for WanVideo, AnimateDiff and ControlNet OpenPose.


See it

Same clip, same detection. Left is what OpenPose produced, right is after the node.

Close to camera — watch the arms and the hand clusters:

Close-up comparison

Full body, dancing — watch the legs and how the skeleton holds together through fast movement:

Full body comparison


Install

ComfyUI-Manager — search for Teskor's Utils.

Manual:

cd ComfyUI/custom_nodes
git clone https://github.com/teskor-hub/comfyui-teskors-utils
pip install -r comfyui-teskors-utils/requirements.txt

Restart ComfyUI. Nodes appear under TS Utils.

Needs numpy and opencv-python, Python 3.9+. PyTorch is deliberately not in requirements.txt — ComfyUI already ships it, and letting pip reinstall it is a reliable way to replace a working CUDA build with a CPU one.


Using it

Drop it between detection and ControlNet:

Load Video → OpenPose Detection → TS Pose Data Smoother → ControlNet OpenPose → Generation

It returns both the cleaned POSEDATA and a rendered preview IMAGE, so you can see what you are feeding forward without wiring up a separate renderer.

Parameters

| Parameter | Default | What it does | |---|---|---| | filter_extra_people | True | Keep only the tracked subject, drop everyone else | | smooth_alpha | 0.7 | Smoothing strength. Higher tracks the raw detection more closely; lower is smoother but lags behind fast motion | | gap_frames | 12 | Longest dropout, in frames, that gets interpolated rather than left empty | | min_run_frames | 3 | Detections that appear for fewer frames than this are treated as noise and removed | | conf_thresh_body | 0.35 | Body keypoints below this confidence are ignored | | conf_thresh_hands | 0.6 | Same, for hand keypoints | | force_body_18 | False | Force the COCO-18 skeleton layout | | smooth_hands | False | Experimental. Also smooth the 21 finger keypoints |

If you only touch one slider, make it smooth_alpha. Everything else is reasonable out of the box.

Arms are smoothed, fingers are not

Worth stating plainly, because "hand jitter" means two different things:

  • Arms, elbows and wrists are part of the body skeleton, so they go through the full pipeline by default — median filter, zero-lag EMA, then a velocity-predictive pass with a step limit. This is what removes the visible shaking.
  • Finger keypoints are a separate 21-point set per hand and are left untouched unless you turn on smooth_hands.

smooth_hands is off by default so that updating the node cannot change output you already like.


Picking the right person

When more than one person is detected, something has to decide who the video is about. This node scores each track on how much of the clip it covers, how large it is (closer to camera), how centrally it sits, and its mean confidence.

That combination matters more than it sounds. Ranking purely by "who appears in the most frames" loses to a steadily-detected bystander the moment the actual subject's detection flickers — which is exactly the footage you are trying to repair in the first place.

Measured against a synthetic sequence with a known ground-truth skeleton, subject-tracking error went from 150.6 px to 10.2 px — about 14.8× more accurate, reproduced across three random seeds. Single-subject clips are unaffected: output is bit-identical to previous releases.


Color Match Sequential Bias

The other node worth knowing about. Chunked generation drifts in brightness, colour balance and contrast between chunks; individually invisible, in sequence every boundary shows up as a step. TS Color Match measures the drift between consecutive chunks and corrects it.

| Parameter | Default | What it does | |---|---|---| | chunk_size | 81 | Must match your generation chunk size. 81-frame chunks → set 81 |

WanVideo Animate Embeds → Combine Frames → TS Color Match → Save Video

Also included

Small utilities that come along for the ride:

| Node | Purpose | |---|---| | TS Rename Files In Dir | Renumber a folder into a clean sequence. Has dry_run — use it first | | TS Save Pose Data | Cache POSEDATA to disk as .npz | | TS Load Pose Data | Load it back, so you can iterate on generation without re-running detection |

Pose cache format

Pose files are .npz. Earlier releases wrote pickles, which is an arbitrary-code-execution format — the load node reads from ComfyUI's input folder, so a pose file shared by anyone else ran with your permissions. Those pickles also embedded the absolute install path of ComfyUI-WanAnimatePreprocess as a module name, so they silently broke whenever that pack moved.

Existing .pkl caches are not read any more. Re-save them through the node, or ask in an issue for the one-off converter script.

TS Rename Files In Dir rewrites names on disk. It refuses to write outside the target directory, renames in two phases so a new name cannot collide with a not-yet-processed old one, and rolls back if anything fails. Still — run it with dry_run first.


Example workflows

In example workflows/:

  • openpose smoother example.json — the smoother on its own
  • wanvideo work flow teskor utils + kijai example.json — full WanVideo pipeline alongside Kijai's nodes

License

MIT — see LICENSE.