RenderSplats4DVideo
The payoff — a moving camera through a moving world
- splats4d
- trajectory
- images
- masks
- disparity
This is the node at the end of the road. Build a 4D splat scene - or load one you saved - and RenderSplats4DVideo turns it into an actual video: it interpolates your camera path to the requested frame count, sweeps time from time_start to time_end across the scene's motion, and renders every frame. Moving camera and moving world, output as a batch of images (plus masks and disparity) you can pipe straight into a video encoder.
The whole point of the pack's video_to_4d_world pipeline is that you take a monocular video, reconstruct it as a 4D Gaussian world, and then re-render it from any camera path you want - including ones the original footage never took. RenderSplats4DVideo is where that promise pays off. Hand it a new trajectory (build one with CameraInterpolationNode, compose one with TrajectoryCompose, or load a saved path) and you get the scene from angles the source camera never saw, with the dynamic objects still moving correctly in time.
How it works
It interpolates the input trajectory ([K,4,4] world-to-camera poses) to num_frames (default 49) via SE(3) interpolation, then loops: at each frame it evaluates the 4D scene at the current time value and renders through the splat rasterizer with your camera_projection and camera_horizontal_fov. Time values are evenly spread between time_start and time_end. render_mode (auto/gsplat/fast/over) picks the backend; max_splats (0 = unlimited) lets you cap complexity for previews. Output resolution is output_width × output_height.
The outputs
- images -
[F,H,W,3], the frames, ready forVHS_VideoCombineor a frame-to-video node. - masks - coverage per frame.
- disparity - depth per frame.
Wire images to a video encoder and you're done - that's the whole workflow.
What to watch
- num_frames vs. fps - 49 frames at 30 fps is under two seconds. Set frames to match your target duration; the node doesn't loop or interpolate between trajectories, it just renders exactly what you asked.
- Time sweep direction -
time_start/time_endin the range 0–1. Reverse them and the motion plays backwards, which is occasionally the right creative call. - Render cost - this is num_frames separate renders of the full scene. Keep
num_framesand resolution modest for iteration, then raise both for the final pass.
Installing it
Part of camera-comfyUI. Manager → Custom Nodes Manager → camera-comfyUI → Install → restart, or:
cd ComfyUI/custom_nodes
git clone https://github.com/Alexankharin/camera-comfyUI.git
cd camera-comfyUI && python install.py
gsplat (from install.py) gives the fast CUDA path; without it you fall back to the torch renderer and 49 frames will test your patience.
Common issues
- Frames are all the same shot - the trajectory has only one pose (or all poses identical), so the interpolated path doesn't move. Feed it a real multi-pose path.
- Motion plays too fast/slow - that's the
time_start/time_endwindow andnum_framesinteracting. Spread the time range across more frames for slower motion. - Long renders - expected for many high-res frames. Render low-res first, preview, then go big.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| splats4d | GSPLAT4D | — | |
| trajectory | TENSOR | Camera path [K,4,4] world-to-camera; interpolated to num_frames. | |
| num_frames | INT | 491–4096 | — |
| time_start | FLOAT | 0.000–1 | — |
| time_end | FLOAT | 1.000–1 | — |
| camera_projection | COMBO | 3 options: PINHOLE, FISHEYE, EQUIRECTANGULAR | |
| camera_horizontal_fov | FLOAT | 90.001–360 | — |
| output_width | INT | 5128–16384 | — |
| output_height | INT | 5128–16384 | — |
| render_mode | COMBO | auto | 4 options: auto, gsplat, fast, over |
| max_splatsopt | INT | 00–10000000 | 0 = unlimited. |
| deviceopt | COMBO | auto | 3 options: auto, cpu, cuda |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| masks | MASK | — |
| disparity | TENSOR | — |