Nodes/ComfyUI-QwenFrameSelector/Qwen Frame Selector
ComfyUI Node

Qwen Frame Selector

Let Qwen Tell You Which Frames Are Worth Keeping

By eddyhhlure1Eddy·Created 10 months ago·Updated 10 months ago· 12
Qwen Frame Selector
  • video
  • images
  • selected_frames
  • scores_json
  • summary
api_keysk-or-v1-e87b456b1f3aefc24042e8320681630172d967d34290518ed87ef1d8bec6a24d
sample_rate30
selection_criteriabalanced
top_percent30
min_score6.0
max_frames0

Stop sorting frames by hand

The annoying part of video work in ComfyUI isn't generating - it's deciding which frames deserve the effort. You generate a clip for img2img, or you want keyframes for i2v conditioning in Wan or LTX, and suddenly you're eyeballing a hundred near-identical frames hunting for the sharp ones. Qwen Frame Selector outsources that judgment call to a vision model. You feed it a video (or an existing image batch), it scores every frame on five quality dimensions, and hands you back just the ones that clear your bar - as a normal ComfyUI IMAGE batch you can preview, save, or pipe straight into img2img or a video sampler.

The fine print: this isn't a local model, it's a paid API call per frame. Know what you're signing up for.

How it actually works

Read the source and the README lines up well enough. In video mode it shells out to FFmpeg and extracts one frame every sample_rate frames (select=not(mod(n,N)), quality 2 JPEGs) into a temp folder. In image mode it skips extraction entirely, saves your IMAGE tensor to temp JPEGs, and analyzes everything you gave it - sample_rate is ignored there. Give it one or the other, never both, or it throws.

Every frame is base64-encoded and POSTed to OpenRouter's chat completions endpoint with qwen/qwen3-vl-235b-a22b-thinking - a real, current 235B-parameter vision model (22B active), served remotely. The prompt asks it to score sharpness, composition, aesthetic, technical, and content each 0–10, plus an overall score and a one-line reason, and return strict JSON. The node then drops anything below min_score, sorts by overall descending, keeps the top top_percent % (capped by max_frames), and re-sorts the survivors into chronological order before returning them.

One honest caveat the README dances around: content_diversity and keyframe_detection are just different prompt instructions. The selection code is always "top N by overall score" - there's no real deduplication or scene-change detection. Great for "best shot of this take," less useful than it sounds for "give me variety."

The inputs that matter

  • selection_criteria - balanced is the sane default; quality_focused if you mostly care about sharpness/noise, aesthetic_focused if you're curating for looks.
  • sample_rate - extract one frame every N frames. This is your cost and time dial. 30 is fine for short clips; go 60–120 on anything long or you'll be waiting on a hundred sequential API calls.
  • top_percent / min_score - the two filters. Start at 30% / 6.0 and tighten.
  • video OR images - exactly one.

Outputs: selected_frames (IMAGE, wire it to Preview Image / Save Image / anything), scores_json (the per-frame breakdown, handy to dump and inspect), and summary (a text report the node prints in its UI box).

Installing it

ComfyUI Manager → search "QwenFrameSelector" → install. Or by hand:

cd ComfyUI/custom_nodes
git clone https://github.com/eddyhhlure1Eddy/ComfyUI-QwenFrameSelector.git
cd ComfyUI-QwenFrameSelector
pip install -r requirements.txt

Restart, and the dependencies are mercifully light - just requests, pillow, numpy, torch, all of which your ComfyUI env almost certainly already has. No model downloads, because nothing runs locally. The one non-Python requirement is FFmpeg in your PATH (the install script checks for it), and an OpenRouter account with API credits. This node actually costs you money per run - budget a few cents for a short clip, more for a long one.

Where people get burned

The shipped API key. Open the node and the api_key field comes pre-filled with what looks like a real sk-or-v1-... key - it's hardcoded as the default in the source. Replace it with your own key, always. At best it's a stale placeholder the author forgot to remove; at worst it's someone's live credential that will bill their account every time you run a workflow. The custom node ecosystem has a real security trauma around trusting what you install (the LLMVISION malware incident), and a hardcoded API key is exactly the kind of hygiene slip to treat with suspicion. Paste in your own key, move on.

Silent API failures. If a call errors, the node quietly assigns the frame a default 5.0 score and keeps going. With min_score at 6.0 you can end up with a batch of junk that "passed" because everything fell back to defaults. If your picks suddenly look random, check your key, your credit balance, and your connection - the node won't tell you it failed.

Sequential slowness. Each frame is one HTTP round trip, ~2–4 seconds, and it doesn't batch. 500 frames is the practical ceiling the README quotes - at the top end that's 25+ minutes and hundreds of billed calls. Raise sample_rate, cap max_frames, and process long videos in chunks.

FFmpeg errors are self-explanatory: ffmpeg -version should print something. If it doesn't, install FFmpeg, add it to PATH, and restart ComfyUI.

Categoryvideo/analysis

Inputs (8)

NameTypeDefaultDescription
api_keySTRINGsk-or-v1-e87b456b1f3aefc24042e8320681630172d967d34290518ed87ef1d8bec6a24d
sample_rateINT301–300Extract 1 frame every N frames
selection_criteriaCOMBObalanced5 options: quality_focused, aesthetic_focused, balanced, content_diversity, keyframe_detection
top_percentFLOAT305–100Keep top X% of frames
min_scoreFLOAT6.00–10Minimum quality score (0-10)
videooptVIDEOInput video for frame extraction and analysis
imagesoptIMAGEInput images for direct analysis (alternative to video)
max_framesoptINT00–1000Maximum frames to select (0 = unlimited)

Outputs (3)

NameTypeDescription
selected_framesIMAGE
scores_jsonSTRING
summarySTRING