APNext QwenVL Video Analyzer
Analyze video frames locally — describe a clip without sending it anywhere
- video
- analysis
- extracted_frames
You've got a video clip and you want to know what's actually in it - to caption it, to turn it into a text prompt, to build an image-to-video workflow that continues from its last frame, or just to index a folder of footage. Sending video to a cloud vision model means uploading frames and paying per call. This node keeps it local: it pulls frames out of the video, hands them to a Qwen3-VL vision model on your own GPU, and returns an analysis string plus the actual extracted_frames it looked at.
It's the video sibling of the QwenVL Vision Analyzer, and it slots into the same local-first story the QwenVL nodes tell: no API key, no per-frame billing, models auto-download to ComfyUI/models/LLM/Qwen-VL/ on first use. If you're already running one QwenVL node in the pack, this one is nearly free to add.
How it works
The node takes a VIDEO input (from a LoadVideo node) - or an IMAGE batch if that's what your pipeline hands you - and does two jobs. First, frame selection: video_section picks start or end of the clip, frame_window says how many frames of that section to consider, and fps_extract decides how many frames to actually pull out for analysis (default 3 - enough to understand a scene, cheap to run). Then the model analyzes those frames with your chosen qwen_model, temperature and max_tokens, and the node returns the write-up plus the frames it used.
Frame decoding is worth knowing about: the pack lists decord as optional-but-commented-out in requirements, because it's unmaintained and not numpy-2 safe. The video nodes fall back to OpenCV automatically - which is to say, it just works, and you don't need to uncomment anything unless you specifically want decord's decoder.
The inputs that matter
video(optional) - the actual clip. ConnectVIDEOfrom LoadVideo, or an IMAGE batch.video_section/frame_window/fps_extract- where in the clip to look, and how much of it to look at.frame_windowhas effectively no limit, so you can scan a whole feature if you're patient.qwen_model- Qwen3-VL 2B–8B, withThinkingandFP8variants. 2B is fine for description; reach for 8B when you need the model to actually reason about what's happening.custom_prompt(optional) - overrides the default analysis instruction when you want something specific ("describe only the lighting and camera movement").keep_model_loaded/use_flash_attention/seed/randomize_each_run- the standard QwenVL set; flash attention is off by default and requires theflash-attnpackage.
Outputs are analysis (the description - wire it into a prompt, a text preview, or a save node) and extracted_frames (the exact frames it looked at, so you can verify it saw what you think it saw).
Install
Standard pack install - ComfyUI Manager (search "comfyui_dagthomas") or:
cd ComfyUI/custom_nodes
git clone https://github.com/dagthomas/comfyui_dagthomas
cd comfyui_dagthomas
pip install -r requirements.txt
Restart, and let the model download on first use. No API keys.
Common issues
- Nothing comes out of LoadVideo - check your loader's output type; the node accepts
VIDEOorIMAGE, but the connection has to match one of them. - Slow on long clips - you're loading and analyzing a model on your own GPU; keep
fps_extractlow (3–5) and use the 2B model unless you need 8B reasoning. - Out of memory - FP8 variants exist for exactly this. And don't enable
use_flash_attentionwithoutflash-attninstalled, or the load may fail.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| video_section | COMBO | start | Extract frames from start or end of video |
| frame_window | INT | 601–999999 | Number of frames to consider from the selected section (no limit) |
| fps_extract | INT | 31–100 | Number of frames to extract from the frame window |
| qwen_model | COMBO | Qwen3-VL-2B-Instruct | Qwen-VL model to use for analysis |
| max_tokens | INT | 102464–4096 | Maximum tokens to generate |
| temperature | FLOAT | 0.700.1–1 | Sampling temperature (lower = more focused) |
| keep_model_loaded | BOOLEAN | true | Keep model in memory for faster subsequent runs |
| use_flash_attention | BOOLEAN | false | Use Flash Attention 2 for better speed and memory (requires flash-attn package) |
| seed | INT | -1-1–18446744073709550000 | Random seed (-1 for random) |
| randomize_each_run | BOOLEAN | true | Generate new seed each run when seed is -1 |
| videoopt | VIDEO,IMAGE | Connect VIDEO from LoadVideo node or IMAGE batch | |
| custom_promptopt | STRING | Custom analysis prompt (overrides default) |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| analysis | STRING | — |
| extracted_frames | IMAGE | — |