Seedance – Image to Video (First + Last Frame)
Seedance First + Last Frame Interpolation
- first_frame
- last_frame
- reference_video
- reference_audio
- video
- last_frame
- frames
- video_url
- video_path
- last_frame_url
First-frame-only video generation is a dice roll. You describe the motion, the model starts from your image, and the ending is whatever it felt like - sometimes great, sometimes a completely different shot. This node removes that bet. You give it a first_frame and a last_frame, and Seedance fills in the middle. The start and end are pinned; only the journey is up for grabs.
Same pack, same DNA: it's an API wrapper around ByteDance's closed Seedance 2.0 model (dreamina-seedance-2-0-260128) on the BytePlus ARK endpoint. No local weights, no GPU work, metered per call. The two images travel to the cloud as PNG data-URIs with explicit first_frame / last_frame roles, and the API interpolates motion between them.
Why this node is the chaining workhorse
The trick that makes it sing is last_frame. Every Seedance node in this pack outputs the final frame of the video it just made as an IMAGE tensor - and this node takes a last_frame as input. So the loop you'll actually build:
LoadImage → SeedanceI2VFirstFrame → last_frame ─┐
↓
SeedanceI2VFirstLastFrame (first_frame ← last_frame above)
You chain clips without a cut: each new shot starts exactly where the last one ended. The obvious extension is a seamless loop - feed the same image into both first_frame and last_frame and the model has to find its way back to the start. It's the closest thing this pack gives you to a closed loop out of the box.
What you actually set
first_frameandlast_frame- IMAGE tensors, both required. Connect anything that outputs an IMAGE: LoadImage, a VAE decode, thelast_frameorimagesoutput of another node.prompt- "Smooth camera movement between the two frames." is the default, and it's hard to improve on for a basic transition. Get specific if you want actual choreography.ratio-adaptiveby default, so the API fits the frames you gave it. If you force a ratio that doesn't match your images, you're asking for a crop.duration- 4–15 seconds for Seedance 2.0.resolution,generate_audio,watermark,return_last_frame- same story as the rest of the pack.
There are also first_frame_url / last_frame_url overrides if your frames are already hosted, plus optional reference_video / reference_audio sockets you reference as [Video 1] / [Audio 1] in the prompt.
The six outputs are the pack standard: video (native VIDEO), last_frame, frames (all frames as a batch), video_url, video_path, and last_frame_url.
Install
ComfyUI Manager, search comfyui-seedance-nodes. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/theclueless-ai/comfyui-seedance-nodes
pip install -r ComfyUI/custom_nodes/comfyui-seedance-nodes/requirements.txt
Light dependency list - requests, Pillow, numpy, opencv-python - and zero model downloads, because the model isn't yours to download. Set ARK_API_KEY as an environment variable or paste it into the api_key field, then restart ComfyUI. Key comes from the BytePlus console.
Where people get burned
- Treating it like a morph. It's interpolation in the generative sense, not a frame-to-frame morph - the model invents the in-between, and a prompt like "turn the vase into a flower" is a request, not a guarantee.
- The usual API stuff. Empty key → instant error; slow jobs (1080p, long duration) can outlast the 600s default
max_wait, so bump it; and every call is metered, so chaining ten clips in one workflow is a real bill, not a hypothetical. Draft at 480p and low duration first. - Frames that don't match. If your two images have wildly different aspect ratios or styles, the "fill" has more to reconcile - keeping them visually consistent gives the model less room to drift.
Inputs (19)
| Name | Type | Default | Description |
|---|---|---|---|
| api_key | STRING | — | |
| first_frame | IMAGE | First frame of the output video. | |
| last_frame | IMAGE | Last frame of the output video. | |
| prompt | STRING | Smooth camera movement between the two frames. | Use [Video 1] / [Audio 1] to reference media. |
| model | COMBO | dreamina-seedance-2-0-260128 | 1 options: dreamina-seedance-2-0-260128 |
| ratio | COMBO | adaptive | 6 options: 16:9, 9:16, 1:1, 4:3, 3:4, adaptive |
| duration | INT | 54–15 | Video duration in seconds. Seedance 2.0 supports 4–15 s. seedance-1-5-pro-251215 is capped at 12 s. |
| resolution | COMBO | default | 4 options: default, 480p, 720p, 1080p |
| generate_audio | BOOLEAN | false | — |
| watermark | BOOLEAN | false | — |
| return_last_frame | BOOLEAN | true | Ask the API for a watermark-free PNG of the last frame. |
| poll_interval | INT | 105–60 | — |
| max_wait | INT | 60060–3600 | — |
| first_frame_urlopt | STRING | HTTP URL override for the first frame. | |
| last_frame_urlopt | STRING | HTTP URL override for the last frame. | |
| reference_videoopt | VIDEO | Connect any ComfyUI VIDEO node (Load Video, another Seedance output, etc.). Takes priority over reference_video_url. Reference as [Video 1] in the prompt. | |
| reference_video_urlopt | STRING | HTTP URL of a reference video. Used only when reference_video is not connected. Reference as [Video 1] in the prompt. | |
| reference_audioopt | AUDIO | Connect any ComfyUI AUDIO node (Load Audio, etc.). Takes priority over reference_audio_url. Reference as [Audio 1] in the prompt. | |
| reference_audio_urlopt | STRING | HTTP URL of a reference audio track. Used only when reference_audio is not connected. Reference as [Audio 1] in the prompt. |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| video | VIDEO | — |
| last_frame | IMAGE | — |
| frames | IMAGE | — |
| video_url | STRING | — |
| video_path | STRING | — |
| last_frame_url | STRING | — |