Upload to S3
The node that ships your generated frames to a backend — presigned URLs and all
- image
Most ComfyUI workflows end in a folder. This one ends in a bucket. UtilS3Upload takes generated images and/or text, PUTs them to presigned S3 URLs, and optionally pings a backend to say "done." It's unabashedly a production-pipeline node - the kind of thing that exists because its author's studio needed to ship storyboard frames from a rendering box to a server. If you're not running a pipeline that hands files off to cloud storage, this node is not for you. If you are, it's a missing piece you'd otherwise have to write a custom node to fill.
How it works
The node accepts presigned upload URLs (one per line, multiline) and matching content. Images are encoded to PNG bytes in memory and PUT to their URLs; text goes up as UTF-8. Uploads run in parallel with up to eight workers. When a callback_url is provided, it finishes by POSTing a JSON payload carrying the job id, scene number, token, and counts of what succeeded and failed - the "my orchestration layer wants to know it's done" part.
Everything is optional, which is both flexible and a footgun. No presigned URLs? It logs a skip and moves on - silently, from a UI perspective. That's the biggest thing to understand: this is a fire-and-forget output node with no outputs to inspect, and its entire status lives in the console log lines.
The inputs
- image_presigned_url / text_presigned_url (STRING, multiline) - presigned S3 PUT URLs, one per line, aligned by index with your images/texts.
- image (IMAGE) / text (STRING) - the payloads.
- callback_url / callback_job_id / callback_scene_number / callback_token (STRING) - the completion callback fields for your backend.
No outputs; it's an output node.
Where you'd actually use it
This is the end of a storyboard batch pipeline: VideoDescribe or SBJsonParser generates the content, UtilSaveFile or similar stages it, and this node pushes frames plus their per-scene text up to cloud storage, then tells the backend which scene just completed so an external UI can show progress. The IS_CHANGED hook returning the current time means it re-uploads on every run rather than caching - exactly what you want for "generate now, ship now."
The practical warnings: presigned URLs expire, so don't let a long generation sit idle before the upload step; and the parallel upload means a slow URL can't stall the batch, but it also means failure counts are per-item and logged, not surfaced. Watch the console, not the graph.
Install
Ships in the IXIWORKS pack - ComfyUI Manager → search ComfyUI-VideoDescription → Install, restart, or clone into custom_nodes/. No extra Python dependencies - it uses stdlib urllib and PIL for the PNG encoding. Niche, absolutely. But for a server-assisted workflow, it's the piece that makes ComfyUI a render backend instead of a toy.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| image_presigned_urlopt | STRING | — | |
| text_presigned_urlopt | STRING | — | |
| imageopt | IMAGE | — | |
| textopt | STRING | — | |
| callback_urlopt | STRING | — | |
| callback_job_idopt | STRING | — | |
| callback_scene_numberopt | STRING | — | |
| callback_tokenopt | STRING | — |
Outputs (0)
No outputs