MiniMax H3 Image-to-Video
Animate a frame, or interpolate between two
- first_frame
- last_frame
- client
- video_url
Most image-to-video nodes take one start frame and hope the model invents a plausible continuation. MiniMax H3 Image-to-Video does that, and then it adds a genuinely rarer party trick: you can also give it a last frame, and the model interpolates between the two. It's the difference between "animate this photo" and "animate a transition from frame A to frame B," and it makes this the node to reach for when you want a shot that resolves somewhere specific rather than drifting.
It's the image-animation sibling of the H3 Text-to-Video node in the same pack, same hosted API, same one-pass picture-plus-stereo-audio at 24fps. Feed it a portrait and a prompt describing the motion, and you get a clip that moves the way you asked - with sound, if your prompt asks for it.
How it works
The node gives you two ways to hand it images, because API-video nodes live in two worlds. The preferred path is a ComfyUI IMAGE tensor:
first_frame(IMAGE) - sent to WaveSpeed as a base64 data URI. This takes precedence the moment it's connected.first_frame_url(STRING) - the fallback when no tensor is connected. Handy for chaining off another node that already emits a URL.
Same split for the ending frame: last_frame (IMAGE) or last_frame_url (STRING). Leave both empty and it's a plain one-frame animation.
Two details in the tooltips are worth reading twice. First, the output canvas follows the first image's aspect ratio - there's no aspect_ratio dropdown here because your image is the canvas. Second, duration snaps to the model's frame grid, so a 5s request lands near 5.2s. Don't fight it.
Inputs that matter
prompt- required. Motion and camera movement. SameAudio:line convention as the H3 T2V node if you want a steered soundtrack.first_frame/last_frame- the two IMAGE sockets above. Connect the first one and you're animating; connect both and you're interpolating.duration- 3–15s, default 5.resolution-480p(~$0.04/s) or768p(~$0.10/s), straight from the tooltip.seed- a real API seed, sent to the model. Fixed value = reproducible video and a cached result you don't get re-billed for;-1randomizes each queue.
Output is video_url (STRING), the pack-wide convention for video nodes - pipe it into Preview Anything to see or download the clip.
Installing and configuring
Part of the ERPK Collection pack. Fastest route is ComfyUI Manager: search erpk, install ERPK Custom Nodes, restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/eRepublik-Labs/comfyui-nodes-erpk.git erpk
cd erpk && pip install -r requirements.txt
It runs against WaveSpeed's API, so you need a WaveSpeed key from wavespeed.ai in Settings > ERPK > API Keys. Nothing is downloaded, nothing runs on your GPU - the server does the generating, the node just polls (10s interval, 15-minute timeout) and hands back a URL.
Common issues
- My first_frame is being ignored - check whether you also left text in
first_frame_url. When a tensor is connected, it wins outright; the URL input is only a fallback for when the socket is empty. - The output is a different aspect ratio than I expected - the canvas follows the first frame's ratio, so a square source gives a square clip. If you want widescreen, start from a 16:9 image.
- Interpolation looks weak - treat the two frames as the same scene, not two unrelated photos. H3 interpolates between them, and like any interpolation it's happiest when the endpoints share composition and lighting.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | STRING | Motion and camera movement. Add an 'Audio:' line to steer the soundtrack. | |
| first_frameopt | IMAGE | First frame as a ComfyUI IMAGE tensor. Preferred input, takes precedence over `first_frame_url` when connected. Sent as a base64 data URI. | |
| first_frame_urlopt | STRING | First frame image URL. Fallback when `first_frame` is not connected. The output canvas follows this image's aspect ratio. | |
| last_frameopt | IMAGE | Last frame as a ComfyUI IMAGE tensor. The model interpolates between the two frames. Takes precedence over `last_frame_url`. | |
| last_frame_urlopt | STRING | Last frame image URL. Fallback when `last_frame` is not connected. | |
| clientopt | WAVESPEED_AI_API_CLIENT | WaveSpeed API client (optional if API key is configured in Settings) | |
| durationopt | INT | 53–15 | Video duration in seconds (3-15). Snaps to the model's frame grid, so a 5s request lands near 5.2s. |
| resolutionopt | COMBO | 480p | Video resolution. Roughly $0.04/s at 480p and $0.10/s at 768p. |
| seedopt | INT | -1-1–2147483647 | Generation seed, sent to the API. A fixed seed reproduces the same video and lets ComfyUI reuse the cached result; -1 generates a new one each queue. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| video_url | STRING | — |