Sora Image-To-Video
Animate any ComfyUI image with Sora — no VRAM, just an API key
- image
- job_id
- status
- result
SoraImageToVideo takes a ComfyUI image, animates it, and hands you back a short video - by shipping the job off to a Sora-compatible API. Before you get excited: nothing runs locally. There are no model files to download, no VRAM burned, no sampler settings to fight. The heavy lifting happens on someone else's server, and that server wants an API key. If you were hoping this was "Sora running on your 3060," stop right there. It's the opposite: a thin API client wearing a ComfyUI costume.
That's not a knock. It earns its place in two situations: you have an OpenAI Sora API key (or a Sora-compatible backend) and want to drive it from inside a graph, or your hardware would take several minutes and every last GB of VRAM to run Wan 2.2 locally and you'd rather pay for a clip. Local video generation is free but heavy; this is the outsource-it path. The pack is just three nodes wrapping the same REST client - this is the image-to-video variant and the most popular of the three.
How it works
The node is pure Python standard library - urllib, no requests, no torch. The README makes a point of saying the core works with no extra packages, and it's telling the truth: there's no requirements.txt in the repo. Pillow and numpy are optional, only for better image handling.
Under the hood it does four things:
- Takes your
imageinput and converts it to PNG bytes - it accepts PIL images, numpy arrays, file paths, and base64, so a plain Load Image node just works. - POSTs multipart form-data with your prompt to
base_url+endpoint, defaulting tohttps://api.openai.com/v1/sora+/videos. - Polls the job until the status turns
succeeded. - Optionally downloads the mp4 to
download_path.
The generation itself is async on the server; the node just waits it out.
The inputs that matter
image(required) - wire any ComfyUI image node into this.prompt(required) - what you want the video to do with that image.duration_seconds(5),aspect_ratio(16:9),fps(24),guidance_scale(7.5) - the knobs you'll actually touch.seed- a string, not a number. Type12345, not12345-as-int; leave it blank for random.api_key- leave blank and setSORA_API_KEYorOPENAI_API_KEYin your environment instead. The node checks the field first, then the env vars.base_url/endpoint- only touch these if you're pointing at a non-OpenAI Sora-compatible backend.download_path- set this or you never actually see the video.
The three outputs are all strings: job_id, status, and result. result is a JSON blob holding the job id, the status, the downloaded file path (if any), and the raw API response. There's no preview node here - you set download_path and open the mp4 yourself.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/maxczc/comfyui-sora-node sora
Then fully restart ComfyUI - the README is emphatic: shut the server down and start it again, don't just refresh the browser tab. ComfyUI Manager can find it if you search the pack title, but the manual clone is the documented path. No model files to fetch and no pip install unless you want the optional image handling - a genuine relief in a scene where most custom nodes drag in a dependency or six.
Where people get burned
- Timeout. Video generation routinely takes longer than the default 120-second cap. See a
TimeoutError? Crankmax_wait_secondsup; that's the first thing I'd change. - No key. You'll get
Provide a Sora API key via the node input or SORA_API_KEY/OPENAI_API_KEY env vars.That means it can't find a key anywhere. - Key in the workflow. Paste it into the
api_keyfield and it's stored in plaintext inside your workflow JSON. Prefer the env var, or a shared .json becomes a leaked paid key. - "It worked, but where's the video?" No preview makes it easy to think nothing happened. Point
download_pathat a folder and clips land as<job_id>.mp4.
Honest summary: it's a small, anonymous pack with no real community footprint, but it's cleanly written and free of dependency hell. If you have a Sora key, it does exactly what it says. If you don't, nothing here helps until you get one.
Inputs (17)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| prompt | STRING | A cinematic video based on this image. | — |
| api_keyopt | STRING | — | |
| negative_promptopt | STRING | — | |
| duration_secondsopt | FLOAT | 5.0 | — |
| aspect_ratioopt | STRING | 16:9 | — |
| seedopt | STRING | — | |
| fpsopt | INT | 24 | — |
| guidance_scaleopt | FLOAT | 7.5 | — |
| base_urlopt | STRING | https://api.openai.com/v1/sora | — |
| endpointopt | STRING | /videos | — |
| metadataopt | STRING | — | |
| webhook_urlopt | STRING | — | |
| wait_for_resultopt | BOOLEAN | true | — |
| poll_intervalopt | FLOAT | 3.00 | — |
| max_wait_secondsopt | FLOAT | 120.00 | — |
| download_pathopt | STRING | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| job_id | STRING | — |
| status | STRING | — |
| result | STRING | — |