Moondream 3 / 3.1 Caption
Fast local captioning with Moondream 3.1 — no cloud, no key
- model
- image
- caption
- performance_json
If you've ever wanted to caption a folder of images for LoRA training without paying for a cloud API or waiting on a giant model, this is the node. Moondream 3.1 Caption is the captioning task on top of the pack's isolated Moondream runtime - a 9B model with only 2B active parameters that's fast enough to feel local, and it needs no API key because it never touches a server.
The whole design is "load once, caption a lot." You feed it a model handle from the Moondream 3.1 Loader, an image (or an IMAGE batch - it'll caption whichever frame you point at via image_index), and it returns the caption as a STRING. That output is exactly what you want feeding a dataset prep workflow: it's natural language, not BLIP-style garbage, and it runs at a speed that makes batch captioning actually pleasant.
Three controls are worth knowing. length is a real toggle - short, normal, or long - and it does what it says; normal is the sensible default for most captioning. max_tokens caps the response (512 default, up to 8192), and image_index lets you pick which frame in a batch gets captioned. Since the worker is the same one shared across all the Moondream nodes, unload_after=false keeps it warm between queues, and stream_output pipes the caption to a connected View Text node live.
The two outputs are caption (the text you actually want) and performance_json - a string with the worker's measured FPS and timing. You can ignore the second one or parse it if you're benchmarking; it exists because Moondream task nodes track how fast the Photon worker is actually going, which is useful when you're tuning batch sizes for video.
Installing it
Install the pack (ComfyUI Manager → "ComfyUI VLM nodes", or clone + requirements.txt), then set up the isolated Moondream runtime exactly as the Loader article describes:
runtime="ComfyUI/models/LLavacheckpoints/moondream31-runtime"
uv venv "$runtime/.venv" --python 3.12
uv pip install --python "$runtime/.venv/bin/python" \
-r ComfyUI/custom_nodes/ComfyUI_VLM_nodes/requirements-moondream31.txt
Accept the Moondream Model License on the loader (that's where license_accepted lives), and the model downloads on first run. Hardware: NVIDIA Ampere-or-newer or Apple Silicon - no ROCm/Intel/CPU path for the local Photon runtime.
Common issues
- "License acceptance required" → go back to the Loader node and flip the toggle. The caption node itself has no license input.
- Empty or wrong caption → check
image_index- with a batch you may be captaining a frame you didn't mean to. - Worker won't start on CUDA → the runtime pins
nvidia-cuda-runtime-cu12==12.9.79on purpose; reinstall the requirements into the venv and don't fight the pin. - Captions too short for your dataset → bump
lengthto long or raisemax_tokens; some tagging workflows want a sentence, not a phrase.
One note on expectations: this is a captioner, not a tagger. If your training pipeline wants comma-separated booru tags, you'll get more mileage from a tagger or from prompting Moondream's Query node with a tag-list instruction. For natural-language captions - the kind that matter for Flux/SDXL training quality - this is the fast local option to reach for.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MOONDREAM31_MODEL | — | |
| image | IMAGE | — | |
| length | COMBO | normal | 3 options: short, normal, long |
| max_tokens | INT | 5121–8192 | — |
| stream_output | BOOLEAN | true | — |
| unload_after | BOOLEAN | false | — |
| image_index | INT | 00–1000000 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| caption | STRING | — |
| performance_json | STRING | — |