SF WaveSpeed VEO 3.1 Image to Video
A target frame
- client
- video_url
If you want a single static image turned into a video with the best motion quality Google currently ships, this is the node. It's the full-strength VEO 3.1 image-to-video - the "standard" model, not the fast variant - and the pack's own docs quote roughly two to three minutes per eight-second clip on WaveSpeed's side. It's slower and pricier than the fast node, but that's the point: this is the "make it look good" pass, not the "does this work at all" pass.
VEO 3.1 is the closed video model the local community treats as the benchmark, and one of the few that generates native, lip-synced audio. You can't run it locally - nobody can - so this node is your doorway. Reach for it when you've already got the perfect first frame and want it to move like footage: product shots, stills from a photoshoot, keyframes you want to extend.
How it works
Same skeleton as every node in the pack. Wire the SF WaveSpeed Client node's output into client, give it an image URL and a prompt, and at run time it POSTs to /api/v3/google/veo3.1/image-to-video and polls until the clip is rendered. No local model, no VRAM, no checkpoints. You get back one video_url string.
The input that makes this node special
Beyond the usual suspects - image (starting-frame URL), prompt, aspect_ratio, duration (4/6/8s), resolution (720p/1080p), generate_audio, negative_prompt, seed, enable_sync_mode - there's one you won't find on the fast node:
- last_frame - an optional ending-frame URL. Give it one and VEO animates from your start image to that ending image, with the motion describing the transition. That's a storyboard tool: you can lock the first and last keyframes and let VEO fill the middle. No other VEO node in this pack has it, and it's the single most underrated input here.
Everything else behaves exactly as the tooltips say: bright starting frames help, describe motion in the prompt rather than restating the image, and flip generate_audio on if you want synced sound in the clip.
Installing it
ComfyUI Manager, search comfyui-stillfront, install. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/razvanmatei-sf/comfyui-stillfront.git
cd comfyui-stillfront
pip install -r requirements.txt
You'll need a WaveSpeed API key from wavespeed.ai. Set it in config.ini (copy config.ini.tmp first), as the WAVESPEED_API_KEY environment variable, or straight into the SF WaveSpeed Client node's api_key field. The README still says to clone stillfront/comfyui-stillfront - that URL is stale; the repo now lives at razvanmatei-sf/comfyui-stillfront.
Where people get burned
The image and last_frame fields are URL strings, not ComfyUI IMAGE tensors. A normal Load Image node outputs a tensor and won't connect; you need something that hands you a URL. This catches everyone once.
The other common failure is patience. Standard VEO 3.1 is not fast - expect minutes per clip even in sync mode (which, despite the toggle's name, still blocks until the job finishes either way). If you're iterating on prompts, switch to the Fast I2V node and save this one for the shots you actually keep. And remember the cost model: this is per-generation API usage, so an invalid key throws Unauthorized instantly, but a good 1080p render bills real money.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| client | WAVESPEED_AI_API_CLIENT | — | |
| image | STRING | Starting frame image URL (JPEG/PNG/WEBP) - connect from Upload Image node | |
| prompt | STRING | Describe motion/story context (e.g., 'Slow dolly zoom on a city skyline') | |
| aspect_ratio | COMBO | 16:9 | Video aspect ratio - 16:9 (landscape) or 9:16 (portrait) |
| duration | COMBO | 8 | Video duration in seconds |
| resolution | COMBO | 1080p | Video output resolution |
| generate_audio | BOOLEAN | false | Generate native audio synchronized with the video |
| last_frameopt | STRING | Optional ending frame image URL for transition effect (JPEG/PNG/WEBP) | |
| negative_promptopt | STRING | Specify undesired generation characteristics | |
| seedopt | INT | -1-1–2147483647 | Random seed for reproducible results. -1 for random seed |
| enable_sync_modeopt | BOOLEAN | false | Wait for generation to complete before returning |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| video_url | STRING | — |