Super Director Tools · Batch Panorama
Six Cameras, One Panorama, One Batch — No Save-Node Spaghetti
- image
- shot_images
- contact_sheet
- metadata_json
You generated a 360° equirectangular panorama. Now you want twelve shots out of it - a wide establishing view, a couple of mediums, a close-up on the thing in the middle - and you do not want twelve copies of the crop node, twelve Save Image nodes, and no way to compare them afterwards.
Batch Panorama is the node that turns a saved shot list into a rendered batch. One panorama in, N perspective views out, plus a contact sheet so you can see all twelve at once, plus a JSON record of exactly what camera each one was.
The job it does
Framing a 360 image is genuinely useful and genuinely annoying. A panorama is a sphere flattened into a 2:1 rectangle, so "the shot from the balcony" is some yaw, pitch and field of view - and the moment you want eight of those, doing it by hand in a crop node means keeping eight sets of numbers in your head and hoping you typed them right. Camera presets fix that: name them, store them, render them.
Note the pack is not a panorama generator - it's plumbing, and it says so. Panorama quality comes from whatever model produced the 2:1 image upstream; framing and seam repair come from here and whatever img2img model you hang off it.
How it renders
presets_json is the whole input contract - a JSON document with schema_version: 1 and 1–64 entries in shots, each carrying shot_id, name, source_id, yaw, pitch, vertical_fov, width, height, aspect_ratio and camera_height. Wire it from the Panorama viewer's third output and it just works.
Each shot is a real perspective camera looking into the equirect texture. Longitude wraps (the sampler adds a wrapped column at each edge so interpolation crosses the seam cleanly), latitude is converted through asin, and camera_height shifts the optical centre along the sphere's radius - a fake dolly inside a unit sphere, not real scene depth. Output is bilinear-sampled and keeps the input's dtype and device. No AI, no upscale.
The batch limits are hard-coded and worth knowing before you design a shot list: 64 shots, 32 megapixels total across the batch, one source_id per document, unique shot IDs.
Inputs and outputs
image is one source panorama - if your upstream emitted a batch, pick a frame first, because the node raises. presets_json takes the Viewer output or hand-pasted JSON. columns (1–8) and thumb_size (64–512) only shape the contact sheet. save_files is off by default; switching it on writes output/director_tools/<batch-dir>/shot_SH001.png, shot_SH001.json and a camera_presets.json with the whole list - each explicit run gets a fresh directory, so nothing overwrites.
shot_images is a single IMAGE tensor batch - shape [shot count, H, W, 3], in list order. Since v0.8.0 that's a real batch, not a list of images. Wire it into Save Image and you get numbered files; wire it into a sampler and it samples all shots at once, which is either exactly what you wanted or a VRAM lesson.
contact_sheet is a labelled preview grid with a 24 px shot-ID band under each thumbnail. metadata_json is the receipt: every shot's settings, the source pixel size, projection info, and where files landed.
The one error everybody hits
IMAGE batch requires all presets to have the same width and height.
Every shot in the list has to share dimensions. That's the price of a real batch, and it's the right trade - but it bites when you frame a 16:9 wide and a 9:16 portrait in the same session. Either normalise the shot list, or run two Batch Panorama nodes and batch the results later. The second error is Expected 1–64 shots, which means your JSON is empty or malformed; check the presets_json widget actually got the Viewer's output rather than a leftover default.
Also: Source ID is a label, not a check. Nothing verifies the image you plugged in is the panorama those presets were authored against. Point a shot list at the wrong file and it will happily render plausible garbage.
Install
Manager → search Super Director Tools, or:
cd ComfyUI/custom_nodes
git clone https://github.com/mch000534/ComfyUI-DirectorTools
Restart, refresh. No models, no pip install - requirements.txt says "No additional dependencies," and the README's claim that it uses only ComfyUI's torch/numpy/Pillow checks out against the shipped code. Don't nest the folder one level too deep; the import failure that causes is silent apart from a red line in the console.
How I'd actually use it
Do the framing in the Viewer with the visual preview, hit Add preset for each angle, then run once in Batch Panorama. Then shot_images → Save Image if you just want the crops, or → an img2img pass with a small denoise if you want detail, remembering you're now sampling twelve latents at once.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| presets_json | STRING | { "schema_version": 1, "shots": [ { "shot_id": "SH010", "name": "Wide", "source_id": "panorama_A", "yaw": 0, "pitch": 0, "vertical_fov": 75, "width": 1920, "height": 1080, "aspect_ratio": "16:9", "camera_height": 0 } ] } | — |
| columns | INT | 31–8 | — |
| thumb_size | INT | 25664–512 | Thumbnail longest edge. Cells follow image aspect ratio; labels have a separate 24 px band. |
| save_files | BOOLEAN | false | Write unique shot PNG and JSON pairs in output/director_tools when explicitly run. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| shot_images | IMAGE | — |
| contact_sheet | IMAGE | — |
| metadata_json | STRING | — |