Nodes/ComfyUI-plugin/VividAI 文生图
ComfyUI Node

VividAI 文生图

It Won't Re-Bill You for a Prompt You Already Paid For

By Neko1t·Created 2 days ago·Updated 2 days ago· 0
VividAI 文生图
  • config
  • prompt
  • IMAGE
◄model►
◄quality1K►
◄ratio1:1►
◄duration0►
◄history_capacity3►
◄node_key►
◄generation_token►
◄model_rules{}►

VividAITextToImage (显示 "VividAI 文生图") turns a prompt into an image using whatever models the VividAI service serves, and it hands the result back as a normal ComfyUI IMAGE. You'd reach for it when the model you want has no weights you can download - that's the honest reason cloud nodes exist, and it hasn't changed: no open weights means no local option at any VRAM.

Where this pack differs from most API wrappers is what happens on the second run. It doesn't fire a new paid job because you nudged the prompt. Read that part before you wire it in, because it will surprise you either way.

What it is, mechanically

The node posts to the VividAI API, waits on a streaming response, downloads the finished file, checks it, and converts it into a native tensor. Nothing is generated on your GPU, and the output socket behaves like any other IMAGE - feed Decode-free downstream nodes, SaveImage, a face detailer, whatever. Local tools don't care where the pixels came from.

Two details worth crediting. The returned file is opened with Pillow and re-saved as PNG instead of trusting the URL suffix, and a multi-frame response is refused outright rather than guessed at. And before submitting, the node re-fetches GET /v1/models, so a retired model fails locally instead of costing you a failed job.

The inputs that matter

Required inputs, in the order you'll touch them:

  • config - the VIVIDAI_CONFIG output from VividAI 配置. No config, no call.
  • model - a free-text string, but in practice you click 刷新模型 (refresh models) and pick from what the service returns. It has no autocomplete of its own, so typos are on you.
  • prompt - multiline, and the tooltip says it accepts plain text or an OpenAI messages/input content object. The node flattens the text parts; if you pass it an image_url or file part it refuses and tells you to use the reference node instead. Plain text is capped at 5000 characters.
  • quality - default 1K.
  • ratio - default 1:1.

Then history_capacity (default 3, range 1–100), and three fields the frontend hides and manages for you: node_key, generation_token, model_rules. Don't hand-edit the hidden ones - the README says so and the UI buttons maintain them.

Output: a single IMAGE. Not a batch, and the service's own format validation assumes one picture per task.

There's also a duration input that does nothing here - this class is shared with the two video nodes and duration is only sent for video. Leave it at 0.

The caching behaviour, which is the whole design

By default the node reuses the material you currently have selected. Change the prompt, change the model, change the quality rules - none of that creates a new task. You get the same image back, instantly and for free, and the graph downstream re-runs on it.

To actually generate, you press 下次运行重新生成 (regenerate on next run), which writes a fresh token, and then run the workflow normally. One press, one task. Older results stay in a local history ring (history_capacity, default 3); clicking 启用此素材 on an older one moves it to the head of the queue and switches the output without touching your prompt or settings.

Is this good? For paid API calls, yes - aggressively so. The alternative is a node that re-bills every time ComfyUI re-executes the branch, which it does for any reason at all, and that's how people burn $20 in an afternoon of fiddling. Under the hood it's the always-dirty trick from ComfyUI plumbing: a fingerprint that never matches (NaN), plus a token deciding "new job" vs "reuse". The cost is that you have to learn the one button. People who don't will sit there editing their prompt and conclude the node is broken.

Failed jobs don't silently fall back to the old image either - the run stops and the previous material stays selected. You find out.

Install

ComfyUI Manager, search ComfyUI VividAI (the repo itself is named ComfyUI-plugin, which is why searching the GitHub name goes nowhere). Manual:

cd ComfyUI/custom_nodes
git clone https://github.com/Neko1t/ComfyUI-plugin
cd ComfyUI-plugin
uv pip install --python /path/to/ComfyUI/python -r requirements.txt

Dependencies are httpx, Pillow, numpy and av, installed into ComfyUI's own interpreter - PyTorch is not installed or upgraded. Restart after. Then: save a profile in a VividAI 配置 node, wire its output here, refresh the model list, pick one, and send the IMAGE output to SaveImage.

Troubleshooting

"所选模型当前不可用" (model not available). The model you typed isn't in the service's list any more. Hit 刷新模型 and pick again. Your existing cached material is still usable, so this won't wreck a saved workflow - it just blocks new generations.

"…不在当前模型的 qualities 配置中" (value not in the model's qualities config). quality and ratio are validated against the per-model rule JSON stored in model_rules. They're plain strings, so nothing stops you typing 4K at a model that only lists 720p, 1080p, 1K, 2K - and then it errors. Expand 当前模型能力配置 and pick what's actually there. The author is explicit that the default values on the node are templates, not universal truth - a model can want something completely different, and the rule JSON is where you say so.

A prompt that starts with { or [. The node tries to parse the prompt as JSON before treating it as text. Valid JSON that isn't an OpenAI content object gives you a format error rather than being sent as-is. Reword the opening.

Chinese error strings. All the pack's validation messages are in Chinese and the frontend doesn't translate them. They're specific enough to act on - paste them into a translator rather than guessing.

CategoryVividAI

Inputs (10)

NameTypeDefaultDescription
configVIVIDAI_CONFIG—
modelSTRING—
promptSTRING,OPENAI_CONTENT支持普通文本,也支持 OpenAI messages/input 内容对象
qualitySTRING1K—
ratioSTRING1:1—
durationINT00–36000 表示不提交时长;模型要求时需填写
history_capacityINT31–100—
node_keySTRING—
generation_tokenSTRING—
model_rulesSTRING{}—

Outputs (1)

NameTypeDescription
IMAGEIMAGE—