TS Pose Data Smoother
OpenPose jitter is ruining your video ControlNet. This is the fix.
- pose_data
- IMAGE
- pose_data
Raw OpenPose output jitters. Keypoints vibrate while the subject stands still, joints drop out for a frame and pop back, a limb occasionally snaps to somewhere impossible. Feed that into ControlNet OpenPose and your generated video inherits every bit of it - the wobble becomes the motion. TS Pose Data Smoother cleans the whole pose sequence before it reaches generation: temporal smoothing, gap filling, outlier rejection, and real subject tracking. It's the flagship of the Teskor's Utils pack and, if you do any pose-driven video on Wan, AnimateDiff, or ControlNet, the reason to install it.
The name is accurate but undersells it. This isn't a moving-average slapped on keypoints - it's a multi-stage pipeline. It decides which person is the subject, then repairs the skeleton frame by frame.
How it works
Stage zero is the part most smoothers skip: OpenPose returns an unordered list of people per frame with no identity across frames, so the node first stitches detections into tracks over the whole clip and picks the main subject. It 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 "appears in the most frames" loses to a steadily-detected bystander the moment the real subject's detection flickers, which is exactly the footage you're trying to repair.
Then the cleanup, roughly: spatial outlier suppression, gap fill, short-run rejection, a 3-tap median filter, a zero-lag EMA (run forward and backward so it can't introduce phase lag), and finally a velocity-predictive causal EMA with a per-step limit - smooths jitter without clipping real motion. The author reports subject-tracking error dropping from 150.6px to 10.2px against a synthetic ground-truth skeleton, across three seeds.
The inputs that matter
You get a pose_data in, a smoothed pose_data plus a rendered preview IMAGE out. Of the eight widgets, a beginner sets maybe three:
- smooth_alpha (0.7) - the one to touch. Higher tracks raw detection more closely; lower is smoother but lags fast motion. Start at the default.
- gap_frames (12) - longest dropout, in frames, that gets interpolated rather than left empty. Bump it if your detector keeps losing the subject for stretches.
- min_run_frames (3) - detections that appear for fewer frames than this are treated as noise and removed.
The rest are reasonable out of the box: filter_extra_people (true) keeps only the tracked subject and drops bystanders; conf_thresh_body (0.35) and conf_thresh_hands (0.6) gate low-confidence keypoints. Two optional flags matter when they apply: force_body_18 truncates the 25-joint BODY_25 skeleton to the first 18 (COCO) for consumers that reject the 25-joint layout, and smooth_hands (experimental) extends the pipeline to the 21 finger keypoints. Hands are left untouched by default - "hand jitter" in the arms is fixed, fingers are not, unless you flip it on. That's deliberate, so updating the node can't change output you already like.
Outputs: pose_data → ControlNet OpenPose or your AnimateDiff/Wan conditioning. IMAGE → a rendered preview of the smoothed subject so you can see exactly what you're feeding forward without wiring up a separate renderer.
Install
Part of Teskor's Utils. ComfyUI Manager → search Teskor's Utils → Install → Restart. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/teskor-hub/comfyui-teskors-utils
pip install -r comfyui-teskors-utils/requirements.txt
Restart, find it under TS Utils/Pose. Deps are numpy and opencv-python only - no model downloads, no PyTorch (ComfyUI already ships it, and the README is explicit about not letting pip touch it).
Where people get burned
Wire it as Load Video → OpenPose Detection → TS Pose Data Smoother → ControlNet OpenPose → Generation, and if your output still shimmies, check two things. First, smooth_alpha - if fast motion looks rubbery, raise it toward 0.9. Second, gap_frames - set too high on fast footage, interpolation over a long dropout produces limbs that stretch. And remember smooth_hands is off: if the fingers are what's jittering, you have to opt in. There are example workflows in the repo - openpose smoother example.json, plus a full WanVideo pipeline alongside Kijai's nodes.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| pose_data | POSEDATA | — | |
| filter_extra_people | BOOLEAN | true | — |
| smooth_alpha | FLOAT | 0.700.01–0.99 | — |
| gap_frames | INT | 120–100 | — |
| min_run_frames | INT | 31–60 | — |
| conf_thresh_body | FLOAT | 0.350–1 | — |
| conf_thresh_hands | FLOAT | 0.600–1 | — |
| force_body_18opt | BOOLEAN | false | Truncate the body skeleton to the first 18 joints (COCO), for consumers that reject the 25-joint BODY_25 layout. |
| smooth_handsopt | BOOLEAN | false | EXPERIMENTAL: also clean and smooth the hand keypoints. Off by default; leaving it off reproduces previous output exactly. |
| smooth_faceopt | BOOLEAN | true | Clean and temporally smooth the native DWPose/OpenPose face keypoints. Enabled by default so facial landmarks do not flicker between frames. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |
| pose_data | POSEDATA | — |