Onion Skinning (Motion Ghosts)
The classic animator's trick, in a ComfyUI node
- images
- past_tint
- future_tint
- onion_skinned
Onion skinning is the animator's old trick of drawing the previous frames underneath the current one so you can see where a character is going. This node brings it to your rendered video: it takes a batch of frames and composites translucent "ghost" copies of nearby frames onto each one, so motion reads as a visible trail. Think of those sports-photo streaks, or the blue/orange motion trails on cycling videos - that's the look.
In this pack it exists to show off the reconstruction: render a mesh sequence from a new angle and onion-skin it, and the ghost trail makes the motion legible in a way a single frame can't. The pack's own onion_skinning_demo.json workflow does exactly this, and MeshSequenceRenderer even has a baked-in onion-skin toggle. This standalone node is the same effect, with every knob exposed, and you can run it on any image batch - it doesn't care whether the frames came from a 3D render, a video loader, or an animation.
How it works
For each frame, the effect pulls frames from frame_interval steps behind (and, optionally, ahead) - so ghost_count of 3 at frame_interval 5 means ghosts at 5, 10, and 15 frames back. Each ghost gets an opacity, optionally fades with distance, and can be color-treated, then it's composited under the current frame.
The three dials that define the look:
- opacity_falloff -
linearfades ghosts out the further back they are,exponentialfades them fast,constantkeeps them all equally strong. Linear is the default and the most natural. - ghost_color_mode -
originalkeeps true colors,tintedwashes ghosts toward your chosen tint,silhouettefills them with solid color. Tinted is the classic blue-past/orange-future look. - blend_mode -
over(normal alpha compositing),add(bright, glowy, great on dark backgrounds),screen(brightens without blowing out whites).
Defaults: 3 ghosts, every 5 frames, 0.3 opacity, linear falloff, tinted, blue for past and orange for future, include_future off. The defaults are genuinely good for a first pass.
Inputs and output
- images - the only required input: your rendered frames as an
[N, H, W, C]batch. Output from MeshRenderer or MeshSequenceRenderer, or any video loader. - Everything else is optional and defaults to the recipe above:
ghost_count(1–10),frame_interval(1–30),ghost_opacity(0.05–0.8),past_tint/future_tint(hex colors),include_future, and the three enum dials.
The output onion_skinned is the same-length image batch, ready for VHS_VideoCombine or SaveImage. Note this node is pure tensor math - no CUDA rasterization, no model. It runs fast and on CPU if that's what your frames are on.
Installing
Ships with the pack; the standard setup applies:
cd ComfyUI/custom_nodes
git clone https://github.com/styletransfer/ComfyUI-TRELLIS2_Motion
cd ComfyUI-TRELLIS2_Motion
python install.py --full
pip install git+https://github.com/microsoft/TRELLIS.git
pip install git+https://github.com/NVlabs/nvdiffrast.git
Restart ComfyUI; it's under TRELLIS2/Effects. (Strictly, for this node alone you only need torch - the heavy TRELLIS and nvdiffrast installs are for the rest of the pack.)
Common issues
- Ghosts too faint to see. At 0.3 opacity on a busy background they'll disappear. Raise
ghost_opacityor switchblend_modetoadd- additive ghosts are hard to miss. - No ghosts at the start of the clip. The first few frames don't have enough history behind them (nothing at index −5 exists), so early frames look plain. That's expected behavior, not a bug - and it's exactly what
include_futureis for if you want a trail on both sides. - Ghosts everywhere, looks like a mess. Drop
ghost_countto 2 and raiseframe_intervalto 10. With a fast-moving subject you want fewer, further-apart ghosts, not a dense smear.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | Rendered video frames [N, H, W, C] | |
| ghost_countopt | INT | 31–10 | Number of ghost frames to show |
| frame_intervalopt | INT | 51–30 | Frames between each ghost (5 = every 5th frame) |
| ghost_opacityopt | FLOAT | 0.300.05–0.8 | Base opacity of ghost frames |
| opacity_falloffopt | COMBO | linear | How opacity decreases with distance |
| ghost_color_modeopt | COMBO | tinted | Color treatment for ghosts |
| past_tintopt | COLOR | #0066FF | Tint color for past frames (blue) |
| future_tintopt | COLOR | #FF6600 | Tint color for future frames (orange) |
| include_futureopt | BOOLEAN | false | Include future frames as well as past |
| blend_modeopt | COMBO | over | How ghosts blend with current frame |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| onion_skinned | IMAGE | — |