Save Seedream Layers PSD
The bridge from Seedream's layer separation to an editable Photoshop file
- base_image
- base_mask
- layers
- masks
- bboxes
- composite_image
ByteDance's Seedream has a genuinely great trick: it separates an image into layers - a background plate, then individual objects with masks and placement boxes. But Seedream is API-only, and layer separation comes back as flat images plus metadata, not as an editable document. Save Seedream Layers PSD is the last mile. It takes those outputs and assembles them into a real smart-object PSD that Photoshop opens losslessly. No Photoshop installed, no API key, no network call - despite the name, this node runs entirely on your machine and just packs tensors into a file.
Where it sits in the workflow
This is the save half of the ComfyUI-PSD-Layers pack (the load half, Load Layers PSD, reads arbitrary PSDs). It's an output node built for one specific upstream: the ByteDance Seedream layer-separation node (ByteDanceSeedreamLayerSeparationNode), which ships separately from this pack. You wire its outputs in top to bottom - the pack's seedream_separation_to_psd example workflow does exactly this and is exposed in ComfyUI's template browser, so you don't have to figure the wiring out blind.
What goes in
- base_image / base_mask - the background plate and its alpha.
- layers / masks - the layer batch and its masks. Note the convention: 1 = transparent, inverted from what most ComfyUI nodes hand you. Wire in the separation node's own outputs and it just works.
- bboxes - the placement boxes. The node reads
name,z_index, andcontent_rectfrom the bbox metadata, so layer names and stacking survive into Photoshop. No metadata? It falls back to index order and full-canvas embedding. - filename_prefix - same template support as SaveImage (
%date:...%, subfolders). Defaults toseedream_layers.
On execution it writes <prefix>_00001_.psd plus a matching preview PNG to your output folder, and returns composite_image - identical to the saved PNG - so you can keep a normal preview downstream.
How it actually builds the file
This is the part worth knowing, because it's a real hack. psd-tools doesn't officially support writing smart objects. The pack works around it by shipping base64 binary templates of the SoLd/PlLd/lnk2 blocks extracted from a real Photoshop file, patching only uuid, transform, and size at runtime - plus a LinkedLayerV8 subclass that writes the contentID field psd-tools drops and Photoshop otherwise rejects. The kind of deep-in-the-file effort you appreciate when the result just opens. Every layer lands as an embedded smart object in z-order, so you get a genuinely editable document, not a flattened raster.
The panel: reorder and hide before you save
Each layer is clickable (alpha-accurate hit testing with a bounding-box highlight). Drag rows to change z order, toggle visibility with the eye icon, then hit Re-save PSD to save again with your edits without re-running the graph. Hidden layers are written into the PSD with visible=false and excluded from the preview PNG, so nothing is destructively lost. Since 1.0.2 the base plate shows up as a fixed bottom row too, hideable but not draggable.
One trap: the save session lives in server memory. After a server restart, run the node once before the Re-save button will do anything.
Install
Same pack, same steps - ComfyUI Manager (search "PSD Layers"), or:
cd ComfyUI/custom_nodes
git clone https://github.com/coeyes/ComfyUI-PSD-Layers
cd ComfyUI-PSD-Layers
pip install -r requirements.txt # psd-tools>=1.18.0, pillow, numpy
psd-tools 1.18+ is a hard requirement; older versions crash with a clear upgrade message. No models download. If the layer count and bbox count don't match, the node logs a warning and pairs them by index order, so keep your separation node's settings consistent.
That's the whole story. If Seedream's layer separation is part of your pipeline, this is the bridge that turns AI-generated objects into a document a human can actually edit - a rare case where the artifact arrives as a real layered PSD instead of a flattened image.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| base_image | IMAGE | base_image from the layer separation node (background plate). | |
| base_mask | MASK | base_mask from the layer separation node (1 = transparent). | |
| layers | IMAGE | layers batch from the layer separation node (bottom to top). | |
| masks | MASK | masks from the layer separation node (1 = transparent, LoadImage convention). | |
| bboxes | BOUNDING_BOX | bboxes from the layer separation node (placement boxes + metadata). | |
| filename_prefix | STRING | seedream_layers | Prefix for the saved files. Supports the same templates as SaveImage, e.g. %date:...%. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| composite_image | IMAGE | Preview image compositing all layers (identical to the saved PNG). |