OG Veo Generate
Veo 3.1 in ComfyUI, With the Sound and the Invoice
- image
- last_image
- reference_images
- frames
- audio
- video_uri
Veo is the one capability open video still hasn't matched: sound effects and dialogue generated in the same pass as the picture. Wan and LTX give you beautiful silent clips you then have to score separately. Veo gives you a person saying a sentence, and the room tone under it, from one prompt. VeoGenerate ("OG Veo Generate") puts that call on your canvas and hands back frames and audio as separate sockets.
Everything else about it is a metered cloud service: your prompt leaves the machine, every clip costs money, and a slow queue is normal.
One node, four modes, no mode switch
No dropdown for text-to-video versus image-to-video. The node inspects what you connected and picks a mode, in this order:
video_urinon-empty and starting withhttp→ extend (continue a previous Veo render)imageandlast_imageboth connected → first + last frame interpolationimagealone → image-to-videoreference_imagesconnected → ingredients, capped at the first three images- nothing but a prompt → text-to-video
Under the hood it calls generate_videos, gets an operation back, and polls every four seconds for up to thirty minutes before downloading the file. Then PyAV decodes it: frames become one batched tensor, the audio stream becomes a Comfy AUDIO dict you can wire into Save Audio or a video combiner. Long waits are structural, not a hang.
And it's a list of modes, not a menu of combinable options - the branches are exclusive except for reference_images, which gets attached whenever it's connected. Wire up an image and a reference batch and you're asking the API for two modes at once, which is how you earn an invalid-argument error. One mode per run.
Inputs and outputs
prompt ships with the literal default a cat reading a book, which is as good a smoke test as any. model is three Veo 3.1 preview builds: veo-3.1-generate-preview plus its -fast- and -lite- variants. duration_seconds is 4–8, resolution is 720p or 1080p, aspect_ratio only 16:9 or 9:16. negative_prompt is only sent when you type something.
reference_images deserves a note: it's one socket, typed IMAGE, and it takes a batch. The code reads up to three entries from that batch, so "up to 3" means batching three images - three separate nodes can't share one input. video_uri has to be an http(s) URI from a previous Veo run (Veo-generated, 720p, referenced within about two days), so it's the loop-back for extending, not a way to load your own footage. For that, use OG Omni Flash.
Outputs are frames, audio, video_uri. frames is a list holding one batched tensor, so downstream sees frames rather than a VIDEO object - hand it to a video combiner yourself. video_uri is the string you feed back in to extend the shot.
And the seed field is decorative. It's there so saved workflows don't error out, and the README says it plainly: the value never reaches the API, because the Gemini Developer API has no seed for Veo. Same prompt, same seed, different clip. Don't build around it.
Cost, and how to not set money on fire
Veo is metered per call and is the most expensive thing in this pack by a wide margin - the pricing conversation around Veo in ComfyUI has been the loudest objection to the whole API-node category. Two habits keep the bill sane: draft with -lite- or -fast- at 720p while you're arguing with the prompt, and fire the full model at 1080p only for the take you keep.
720p is genuinely the soft option, and people have complained that Veo output through the API looks lower-resolution than they expected. If it looks mushy, try 1080p before you blame the prompt. Every output also carries an invisible SynthID watermark - Google's, not the node's.
Install
Manager → search OnlyGemini → Install Custom Nodes → restart. Or clone https://github.com/choquevolqueta/OnlyGemini into ComfyUI/custom_nodes and run pip install -r requirements.txt inside it.
This node needs av (PyAV, the FFmpeg bindings that turn the returned mp4 into frames and audio) and google-genai; the same file also pulls simple-lama-inpainting and opencv-python for the LaMa node. A key goes in GEMINI_API_KEY, a .env in the pack folder, or the api_key field - which also takes an env var name, and is a plain widget, so a pasted key rides along in any workflow you share.
Where people get burned
400 / invalid argument when extending. video_uri must be an http(s) URI from a prior Veo generation, still valid; a path to a local file or a random URL is a 400. For arbitrary video, this is the wrong node.
A long stare at a progress bar. The poll loop allows thirty minutes and nothing streams progress at you. Let it cook.
last_image on its own is ignored - first+last needs both image and last_image; one alone falls through to image-to-video.
API key required. Nothing resolved. Export GEMINI_API_KEY and restart ComfyUI.
Filtered or refused. Same Google moderation as the image nodes, and prompts about recognizable people are what trip it. The community's two standing complaints about Veo are exactly this and the pricing; the node can't fix either.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | STRING | a cat reading a book | — |
| model | COMBO | veo-3.1-generate-preview | 3 options: veo-3.1-generate-preview, veo-3.1-fast-generate-preview, veo-3.1-lite-generate-preview |
| aspect_ratio | COMBO | 16:9 | 2 options: 16:9, 9:16 |
| duration_seconds | INT | 84–8 | — |
| resolution | COMBO | 720p | 2 options: 720p, 1080p |
| api_key | STRING | Gemini API key or env variable name | |
| seed | INT | 69-1–2147483646 | — |
| negative_promptopt | STRING | — | |
| imageopt | IMAGE | First frame image for first+last mode. | |
| last_imageopt | IMAGE | Last frame image. Connect with first_image for first+last mode. | |
| reference_imagesopt | IMAGE | Reference images for ingredients mode. Up to 3. | |
| video_uriopt | STRING | URI from previous Veo output. For extend mode. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| frames | IMAGE | — |
| audio | AUDIO | — |
| video_uri | STRING | — |