Nodes/Teskor's Utils/TS Pose Keypoint Smoother (DWPose/OpenPose)
ComfyUI Node

TS Pose Keypoint Smoother (DWPose/OpenPose)

Stop OpenPose from shaking — or your generated video will inherit every wobble

By teskor-hub·Created 8 months ago·Updated 9 days ago· 4
TS Pose Keypoint Smoother (DWPose/OpenPose)
  • pose_keypoints
  • IMAGE
  • pose_keypoints
filter_extra_peopletrue
smooth_alpha0.70
gap_frames12
min_run_frames3
conf_thresh_body0.35
conf_thresh_hands0.60
render_resolution768
smooth_handsfalse
smooth_facetrue

You've built the dream workflow: real footage in, DWPose detects the person, pose ControlNet drives image-to-video, and the subject still comes out vibrating like they're standing on a washing machine. Arms shiver when the person is perfectly still, a wrist drops out for one frame and pops back, a limb snaps to somewhere anatomically impossible. That's not your model being bad - that's raw detection noise, and the video generator faithfully copies it because the ControlNet skeleton is your condition.

TS Pose Keypoint Smoother is the fix that sits between the detector and the ControlNet. It takes the standard POSE_KEYPOINT output that comfyui_controlnet_aux's DWPose/OpenPose nodes emit, cleans the whole clip, and hands you back a rendered pose image that's actually stable. The pack it ships in is Teskor's Utils - a small, MIT-licensed collection with an unusually careful author. In video-control workflows this is the node that quietly makes the difference between "close enough" and "usable."

How it works

It's not one filter, it's a small pipeline, and it works over the whole clip rather than frame by frame. The body skeleton gets a 3-tap median filter, then a zero-lag EMA - the same exponential smoothing run forward and backward so the phase lag cancels out - then a velocity-damped pass that lets fast motion through while still killing vibration. Dropped detections get interpolated across up to gap_frames of missing frames instead of leaving a hole, and blips that only appear for a frame or two get discarded as noise.

Face landmarks and (optionally) finger keypoints are smoothed in a body-relative coordinate frame, so moving your wrist across the image reads as real motion, not jitter - only the local vibration gets dampened. The node also tracks the subject across the clip: when multiple people are detected, it scores each track on how much of the clip it covers, how close to camera it is, how central it sits, and its mean confidence, then keeps the one it thinks the video is about. That matters more than it sounds - ranking purely by "who appears most" loses to a steadily-detected bystander the moment the real subject's detection flickers, which is exactly the footage you're trying to repair.

The inputs that matter

You get a pose_keypoints input and one output worth caring about: the rendered IMAGE, which is a DWPose/OpenPose-style skeleton drawn on black at render_resolution (768 by default - you almost never need the source video's full resolution, and keeping it lower keeps long batches fast). Wire that IMAGE into your ControlNet OpenPose. The second pose_keypoints output carries the cleaned data if you want to cache it or process it further.

If you only touch one slider, make it smooth_alpha (0.7 default). Higher tracks the raw detection more closely, lower is smoother - but smoothness trades off against lag on fast movement, so a dancer usually wants a higher value than a seated interview where jitter is the whole problem. The rest of the defaults are honestly fine: filter_extra_people keeps only the tracked subject, gap_frames (12) governs how long a dropout gets interpolated, and the two conf_thresh values drop low-confidence body and hand points before rendering.

One trap to know about before you're confused by it: "hand jitter" means two different things. Arms, elbows and wrists are part of the body skeleton, so they're cleaned by default. The 21 finger keypoints per hand are a separate set that's left alone unless you flip on smooth_hands - experimental and off by default, partly so updates never silently change output you already like. Face keypoints are smoothed natively by default; turn smooth_face off only if raw facial micro-motion matters more to you than flicker removal.

Installing it

Through ComfyUI Manager, search for Teskor's Utils and install. Manual install is the standard two-liner:

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

Then restart ComfyUI and the node appears under TS Utils > Pose. The dependencies are just numpy and opencv-python - no model downloads, and PyTorch is deliberately left out of requirements.txt because ComfyUI already ships a working build and letting pip touch it is how you accidentally end up on a CPU-only install.

Where people get burned

The most common mistake is wiring the wrong output into pose_keypoints. DWPreprocessor has two outputs: the already-rendered skeleton IMAGE and the raw POSE_KEYPOINT data. This node wants the second one - feed it the rendered image and you'll get a type error. Give it the whole batch of frames, not a single frame; the smoothing and tracking are inherently over the sequence, which is the whole point. Start with smooth_alpha, and only touch the rest when you've confirmed the jitter survives that.

CategoryTS Utils/Pose

Inputs (10)

NameTypeDefaultDescription
pose_keypointsPOSE_KEYPOINT
filter_extra_peopleBOOLEANtrue
smooth_alphaFLOAT0.700.01–0.99
gap_framesINT120–100
min_run_framesINT31–60
conf_thresh_bodyFLOAT0.350–1
conf_thresh_handsFLOAT0.600–1
render_resolutionINT76864–4096
smooth_handsoptBOOLEANfalseEXPERIMENTAL: also clean and smooth the hand keypoints. Off by default; leaving it off reproduces previous output exactly.
smooth_faceoptBOOLEANtrueClean and temporally smooth the native DWPose/OpenPose face keypoints. Enabled by default so facial landmarks do not flicker between frames.

Outputs (2)

NameTypeDescription
IMAGEIMAGE
pose_keypointsPOSE_KEYPOINT