happyhorse-image-to-video
Happyhorse-image-to-video has two image sockets, and one of them is a typo
- image_urls
- image_urls
- video
- url
- all_urls_json
- task_id
- raw_json
- credits_consumed
- credits_left
Open this node and you'll see two required IMAGE inputs: image_urls and image_urls - yes, the second one has a trailing space in its name. That's not you misreading the canvas. KIE's own documentation page lists the parameter twice, once cleanly and once with a stray space, and this pack builds its widgets mechanically from those parameter tables. The generator faithfully gave you both.
Connect your first-frame image to image_urls and leave image_urls empty. The trailing-space field maps to a payload key the API doesn't recognise, so filling it in doesn't help anything and leaving it blank doesn't hurt.
Why you'd use this one over the 1.1 sibling
Two reasons. It has a seed (1546095068 by default, 0 to 2147483647), which the HappyHorse 1.1 image-to-video node doesn't - so this is the HappyHorse node where "same input, same output" is at least nominally possible. And its duration is a proper INT from 3 to 15, rather than the float-with-integer-docs situation on the 1.1 node.
Against that: it's the earlier generation of the model, so quality is whatever HappyHorse's first public API version delivered. If you're chasing the multi-shot consistency reputation that made this model famous - and the community's read is that it genuinely holds a character across cuts better than most - the newer 1.1 nodes are where the marketing points. Try both, they cost the same kind of money.
The inputs
prompt and image_urls are required. The prompt is text describing the video, any language, capped at 5000 non-Chinese characters (2500 Chinese); overflow is truncated rather than rejected, so keep an eye on the counter.
The docs for the first frame are specific: JPEG/JPG/PNG/WEBP, width and height at least 300px, aspect ratio between 1:2.5 and 2.5:1, up to 10MB. The pack converts your tensor to PNG and uploads it before submitting the job.
resolution is 1080p (default) or 720p. duration is an integer 3–15 seconds, default 5 - the slider is the knob, and the seconds are real seconds, so a 15s render is a much bigger bill than a 5s one. seed is there for reproducibility, though whether the provider honours it is always "if supported" in KIE's own phrasing.
timeout_seconds (default 1200) and callback_url (empty unless you're running webhooks) round it out.
Outputs
video is the native ComfyUI video object. url and all_urls_json give you result links, task_id identifies the job, raw_json is the provider's response verbatim, and credits_consumed / credits_left are floats you can log. The node prints the same credit numbers as a receipt after each successful run. Results are archived under ComfyUI/output/KIE-Results/videos/ so a KIE-side URL expiring doesn't lose you the clip.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/felipederosilva/ComfyUI-KIE-Nodes-Next
cd ComfyUI-KIE-Nodes-Next
pip install -r requirements.txt
Restart ComfyUI afterwards. The dependency list is short and unremarkable - requests, Pillow, numpy, PyYAML - and there are no model files, since HappyHorse's weights were never released. One-click Windows installer lives in dist/.
Key once: Settings → KIE.ai Nodes Next → Connection. Paste it, let it validate, and forget it. Headless installs can set KIE_API_KEY, which overrides the saved key.
Getting stuck
The node does nothing useful when you wire the wrong socket. If you connect the image to image_urls (trailing space) instead of image_urls, the request goes out without a first frame and the provider rejects it. If you see a validation error mentioning the image, that's the first thing to check.
Aspect ratio rejections. Anything more extreme than 2.5:1 in either direction fails before generation. Crop before you animate.
"Timed out waiting for KIE task …" - the render continues server-side and you're still charged. Recover the task id from the message and check it with the Task Status node.
Identical rerun, no new video, no new charge. That's ComfyUI's cache doing its job. Change the seed or the prompt and it will submit.
A step of 1 on duration. The widget only accepts whole seconds; KIE's docs say the same. Don't expect fractional values to do anything clever.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | STRING | A cat running on the grass | Text prompt describing the video to generate (any language). Max 5,000 non‑Chinese characters or 2,500 Chinese characters; extra content is truncated. |
| image_urls | IMAGE | — | |
| image_urls | IMAGE | — | |
| resolutionopt | COMBO | 1080p | Output video resolution. Valid values: 720P, 1080P (default). |
| durationopt | INT | 53–15 | Output duration in seconds. Must be between 3 and 15. Defaults to 5. |
| seedopt | INT | 15460950680–2147483647 | Random seed for reproducibility (if supported). |
| timeout_secondsopt | INT | 120030–7200 | — |
| callback_urlopt | STRING | Optional KIE callback URL. Leave empty for normal ComfyUI use. |
Outputs (7)
| Name | Type | Description |
|---|---|---|
| video | VIDEO | — |
| url | STRING | — |
| all_urls_json | STRING | — |
| task_id | STRING | — |
| raw_json | STRING | — |
| credits_consumed | FLOAT | — |
| credits_left | FLOAT | — |