GPU Motion Renderer
Edit the timeline as JSON, render motion on the GPU
- images
- IMAGE
Most slideshow work in ComfyUI has an uncomfortable secret: you're either buying a render with a heavy model, or you're assembling Ken Burns moves by hand with a dozen transform nodes. SlideshowForge_GPURenderer (display "GPU Motion Renderer") takes a third path - it renders procedural pan/zoom motion and transitions straight on the GPU with PyTorch and Kornia, no diffusion checkpoint anywhere in the graph. You feed it a timeline JSON and a batch of photos, and out come the actual animated frames, ready for any video encoder.
How it works
It's the second half of the MSCH Slideshow Forge pair. Its partner, the Slideshow Director, turns your image batch into an editable timeline - a JSON document holding source image indices, per-shot motion (Ken Burns pan/zoom), durations, and transition choices, generated from presets like classic Ken Burns, dynamic wipes, or slow cinematic, with total-duration, per-image, or beat-sync timing. The GPU Renderer consumes that JSON (timeline_json) against the same image batch (images) and samples the motion at your fps, producing one IMAGE frame per output frame.
The beautiful part is the split. Because the timeline is plain JSON, you can edit it like text - hand-tweak a shot's duration or swap a transition, paste it back into the Director's timeline_json_in, and re-render only the plan you changed. No dragging keyframes across a canvas. The renderer's only job is "read JSON, animate images," which keeps it small and fast.
The inputs that matter
timeline_json- a STRING socket (connect the Director's output; don't paste it as a widget).images- must be the same image batch the Director used; the JSON indexes into it by position, so mismatched sources mean shots pointing at the wrong photos.fps- output frame rate. Must match the plan's fps to land durations correctly.
The optional inputs are about resource control rather than look: render_chunk_frames (default 64) renders in chunks so a long timeline doesn't spike VRAM; precision (fp16/fp32) and device (auto/cuda/cpu) let you trade quality for memory; max_output_bytes_gb (default 8) is a hard guard - if the frame batch would exceed it, the node refuses rather than OOMing your session. If you're on a small GPU, chunking down and fp16 is how a 4K timeline still fits.
Wiring it
SlideshowForge_Director → SlideshowForge_GPURenderer → Create Video / Video Combine. Output is a single IMAGE socket (the brief's output is literally named IMAGE), a batch of rendered frames; it doesn't emit audio, so the Director's separate audio output is yours to route to the encoder.
Install
Slideshow Forge is one component of the unified MSCH Nodes pack (35 nodes, one install):
cd ComfyUI/custom_nodes
git clone https://github.com/mariobilly/msch-comfyui-nodes.git
cd msch-comfyui-nodes
python -m pip install -r requirements.txt
(ComfyUI Manager: search "MSCH Nodes" / msch-comfyui-nodes, restart.) Kornia is in the pack's base requirements, so no extra model or pip step for GPU rendering.
Gotchas
The recurring trap is the shared image batch: Director and Renderer must see the identical images, in the same order, or every index in the JSON lands on the wrong photo - the pack docs say as much. Second, don't confuse this with the heavier one-node marioslideshow engine: Slideshow Forge is the procedural, JSON-editable, no-model path. If your timeline isn't animating, the usual cause is fps disagreement between plan and renderer, not a missing model. And if the run dies on memory, resist fp32 - chunk the render instead.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| timeline_json | STRING | — | |
| fps | INT | 301–120 | — |
| render_chunk_framesopt | INT | 648–512 | — |
| precisionopt | COMBO | fp16 | 2 options: fp16, fp32 |
| deviceopt | COMBO | auto | 3 options: auto, cuda, cpu |
| max_output_bytes_gbopt | FLOAT | 8.000.5–256 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |