Duke Stereo Video (SBS)
Make your flat ComfyUI video actually 3D in a VR headset
- images
- depth_maps
- video_path
You've got a nice generated video sitting in your ComfyUI workflow, and you want to actually watch it with depth on a VR headset. This is the node for that specific job: it takes your video frames plus a matching depth map per frame, warps them into left-eye and right-eye views, and writes a side-by-side (SBS) MP4 that VR players will happily play. Nothing gets sent anywhere, no API key, no cloud converter - it's all local math over your own frames.
The pipeline it fits into is straightforward: load a video, run a depth estimator (the README suggests LeReS or similar; the KB's depth-estimation essay covers the usual suspects), and hand both the frames and the depth maps to this node. That's the whole deal - one output node that both warps and encodes. This is a genuinely rare capability in ComfyUI: most of the ecosystem's stereo work is still done with standalone tools like iw3 (nunif) or owl3d, so if you want to stay in the graph this is one of the few native options.
How it actually works
For every frame, the node does three things. First it blurs the depth map with an edge-aware blur (depth_blur with depth_blur_edge_threshold), so depth flicker is smoothed out without smearing object silhouettes. Then it warps the image twice using the depth map to shift pixels - once at +divergence for the left eye, once at -divergence for the right - and stitches the two results side by side (so the output is double the input width). Finally it pipes those frames straight into ffmpeg through a background writer thread, encoding H.264/yuv420p, which is exactly the format VR players want.
The RAM efficiency is real: frames stream into a bounded queue and get written out as they're produced, so a 30-second clip doesn't balloon your memory like stacking every SBS frame in a tensor would. It also auto-scales your depth maps to the frame size, tolerates single- or three-channel depth, and rescales 0–1 depth to 0–255 for you - the node is more forgiving about input format than most of this ecosystem.
The one thing to know before you get excited: this is "stereo from a single view," which means the depth map can't see around objects. Push divergence hard and you'll expose seams and occluded background that no fill technique can truly invent. As the depth-estimation doc puts it, motion has to stay subtle or the image starts tearing.
The inputs that matter
imagesanddepth_maps- your frames and one depth map per frame. Everything starts here.divergence(default 2.5) - the 3D strength. Higher = more depth, more artifacts. This is your main dial.convergence_point(0–1) - where the zero-parallax plane sits. Crank toward 1.0 and depth pops behind the screen; near 0 and it comes out toward you.fill_technique-polylines_soft(default),polylines_sharp,naive, ornone. The polylines methods are the high-quality gap fillers for the seams warping creates;naiveis fast and crude,noneleaves holes.output_path- supports format strings like%date:yyyy-MM-dd%,%time:HH-mm-ss%,%divergence%,%width%x%height%, plus~expansion and automatic_001suffixing when the file exists.
It returns a single video_path (STRING) - the full path to the MP4 it wrote, which you can display in the UI to confirm where your file landed. fps and crf control encoding (lower crf = better quality); separation adds a manual horizontal offset on top of the depth-driven one; stereo_offset_exponent (default 2.0) shapes the non-linear depth curve.
Installing it
Via ComfyUI Manager, search "ComfyUI-DukeStereo" and install. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/killertofu86/ComfyUI-DukeStereo.git
pip install -r ComfyUI-DukeStereo/requirements.txt
Then restart ComfyUI. A couple of real gotchas: ffmpeg has to be on your PATH as a system binary (the README lists it as a requirement but it's not in requirements.txt, and the node shells out to it), and transformers sits in requirements.txt but the shipped code never imports it - it's vestigial, leftover from an earlier version. This node does not estimate depth for you; you must supply the depth maps.
Common issues
The default output_path is /ComfyUI/output/..., an absolute path that doesn't exist on most installs. Change it - it's the first thing that'll bite. The node creates the directory and checks write permission up front, but if ffmpeg isn't installed the writer thread fails, and the error can be easy to miss. And be patient on the first run: numba JIT-compiles the warp kernels, so the first execution can feel sluggish before it warms up. If tearing appears in your output, back the divergence down before you blame the node.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| depth_maps | IMAGE | — | |
| output_path | STRING | /ComfyUI/output/stereo_%date:yyyy-MM-dd%_%time:HH-mm-ss%.mp4 | — |
| fps | INT | 241–120 | — |
| divergence | FLOAT | 2.50–50 | — |
| separation | FLOAT | 0.0-5–5 | — |
| convergence_point | FLOAT | 1.000–1 | — |
| stereo_offset_exponent | FLOAT | 2.00.1–4 | — |
| fill_technique | COMBO | 4 options: polylines_soft, polylines_sharp, naive, none | |
| depth_blur | INT | 60–50 | — |
| depth_blur_edge_threshold | FLOAT | 6.00–50 | — |
| crf | INT | 190–51 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| video_path | STRING | — |