Slideshow Director
Slideshow Director edits your image batch into a film
- images
- audio
- timeline_json
- image_count
- audio
Slideshow Director is the half of MSCH Slideshow Forge that does all the thinking. Feed it a batch of images and it decides, shot by shot, how long each one holds, which direction it drifts, and how it hands off to the next frame - then it hands that whole plan to the pack's other node, GPU Motion Renderer, which actually paints the frames. No diffusion checkpoint, no API key, no video editor. Most of us export a pile of stills and end up doing the pan-and-zoom in After Effects or DaVinci anyway; this node moves the edit itself into the graph. And because it's seeded, the same images plus the same settings reproduce the same edit every time.
How it thinks
The key design choice is that the Director never renders a pixel. It builds an editable plan - a timeline - and the renderer executes it later. Each of the three style presets is really a weighted rule table: a motion pool (zoom in/out, pans, diagonals), a transition pool (crossfades, blur dissolves, wipes), per-shot and transition duration ranges, easing curves, and guardrails like "no immediate repeat of the same motion." A seeded RNG draws from those tables, so the randomness is structured - variety without a jarring cut every other frame. The output is plain JSON describing, per segment, the source image index, motion type and parameters, easing, and duration.
Beat-sync mode is where this gets fun. It runs librosa's onset-strength and tempo tracking over your audio - classical DSP, no AI model involved - then places cuts on the detected beat grid instead of on random durations.
The inputs that actually matter
Beginners set four things and leave the rest alone:
- images - your IMAGE batch, and it has to be the same batch you feed the renderer, since the timeline only stores indices into it.
- preset -
classic_ken_burns,dynamic_wipes, orslow_cinematic. The names tell you exactly what you get: slow crossfades and gentle zooms versus feathered wipes with snappier cuts. - duration_mode -
total_duration(fit every image into one target length, the default),per_image_duration(each shot gets an equal dwell), orbeat_sync. Start with total. - seed - this is your reproducibility lever; bump it to get a different edit.
Optional but worth knowing: shuffle_order, loop (adds a transition from the last shot back to the first), canvas_fit (cover crops to fill; the two contain_* options letterbox with a blurred or black backdrop), and timeline_json_in - paste an earlier timeline back in and the node validates it against its schema and regenerates only if it's broken (on_invalid_json controls whether a bad paste errors or falls back).
What comes out
Three sockets: timeline_json (the plan, as a string - you can stare at it, save it, or edit it by hand), image_count (handy for sanity checks and wiring into encoder nodes), and audio, passed straight through for the video encoder. The wire that matters is timeline_json → the GPU Motion Renderer's timeline socket, then the renderer's IMAGE frames into a Create Video or VideoHelperSuite node.
Installing it
Manager support is in flux right now - the pack only hit the Comfy Registry on 2026-09-06 and the Manager listing is still pending - so the dependable route is git:
cd ComfyUI/custom_nodes
git clone https://github.com/mariobilly/msch-slideshow-forge.git
# then, in the same Python env as ComfyUI:
python -m pip install -r msch-slideshow-forge/requirements.txt
Windows portable users point python_embeded\python.exe at that requirements file instead. The dependencies are torch, kornia, numpy, and librosa - that last one is the audio-analysis heavyweight, and it's imported at module load, so skipping it doesn't just break beat-sync, it stops the node from loading at all. There are no diffusion model weights to fetch; rendering is procedural. One note: the README says this standalone repo is being superseded by the author's unified MSCH Nodes pack - if you're starting fresh, you may want that one instead and to follow its migration guide, since running both installs double-registers nodes.
Where people get tripped up
- Beat-sync with no audio throws immediately: "requires an 'audio' input." Connect a Load Audio node's AUDIO output - it won't read a file itself.
- Beat-sync skipped some of your images. If the track doesn't have enough detected beats to cut on, not every image makes the edit; the console warns you. Lower
beats_per_imageor trim the batch. total_durationis a target, not a promise. If it's infeasible for your image count at the preset's per-shot minimums, the node clamps to those minimums and records the shortfall in the timeline's residual field rather than silently dropping shots.
Inputs (16)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| preset | COMBO | classic_ken_burns | 3 options: classic_ken_burns, dynamic_wipes, slow_cinematic |
| duration_mode | COMBO | total_duration | 3 options: total_duration, per_image_duration, beat_sync |
| total_duration | FLOAT | 30.01–3600 | — |
| per_image_duration | FLOAT | 3.00.3–60 | — |
| fps | INT | 301–120 | — |
| seed | INT | 00–18446744073709550000 | — |
| audioopt | AUDIO | — | |
| beats_per_imageopt | INT | 21–32 | — |
| timeline_json_inopt | STRING | — | |
| on_invalid_jsonopt | COMBO | error | 2 options: error, regenerate |
| shuffle_orderopt | BOOLEAN | false | — |
| loopopt | BOOLEAN | false | — |
| canvas_fitopt | COMBO | cover | 3 options: cover, contain_blur_bg, contain_black_bg |
| output_widthopt | INT | 00–8192 | — |
| output_heightopt | INT | 00–8192 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| timeline_json | STRING | — |
| image_count | INT | — |
| audio | AUDIO | — |