Create360SweepVideoFramesNode
Spin a 360° image into a sweep video without ever opening Blender
- images
You've got an equirectangular 360° image - maybe generated by a 360 LoRA, maybe an HDRI you downloaded - and you want a video of the camera gliding around it. The obvious move is to load it into Blender, add a camera, keyframe a rotation, and render. The obvious move is also overkill. This node is the shortcut: feed it the image, and it cranks out the individual frames of a full 360° sweep, saved straight to disk.
It ships in ProGamerGov's ComfyUI_pytorch360convert_video pack, from the same author who makes the popular Qwen 360° LoRA and the ComfyUI_preview360panorama viewer. The author himself points people here when they ask how to turn 360s into video, so this is the intended path, not a random side tool. No models to download, no API key - the whole thing is one PyTorch function.
What it actually does
Inside, the node uses the e2p function from the pytorch360convert library to re-project the equirectangular image into a perspective view, one frame at a time. start_yaw_deg to end_yaw_deg (default 0→360, i.e. a full spin) is divided into duration_per_image × fps frames, and each frame is rendered at a different yaw angle. It's a pure math operation, no diffusion involved, which is why it's fast and runs happily on CPU.
The few inputs that matter:
images- your equirectangular image(s), straight out of whatever generated them.fov_h/fov_w- horizontal and vertical field of view in degrees. This is where people get burned (more below).width/height- output frame size.duration_per_imageandfps- together they set your frame count. The default 5 seconds at 60fps means 300 frames per image, which is a lot of PNGs.total_duration- set this above 0 and it overridesduration_per_image, splitting the total evenly across all input images.speed_profile-constantfor a uniform spin,ease_in_outif you want it to slow down at the start and end like a proper camera move.vertical_mode-none,during(adds a sine or linear pitch wobble while rotating), orseparate(appends a dedicated up-over-the-pole sweep at the middle yaw).
Frames land in <output_dir>/video_frames/ with your filename_prefix and a zero-padded index, in whatever save_format you pick (PNG default). The node is an output node, so it doesn't return a tensor - it shows you a preview of a few frames and writes the rest.
The FOV trap
Here's the gotcha that produces subtly stretched videos: the defaults are fov_h=120, fov_w=100 with width=1920, height=1080. For undistorted perspective, your FOV ratio should match your pixel aspect ratio - fov_h / fov_w = width / height. 120/100 = 1.2, but 1920/1080 = 1.78. Result: vertical stretching. Fix it by setting fov_w so the ratio lines up - for 1080p with fov_h=120, use fov_w = 67.5. Play with the numbers; a narrower FOV gives a more telephoto, "zoomed-in" feel.
Installing it
ComfyUI Manager is the easy route - search for "pytorch360convert" (the pack title is ComfyUI_pytorch360convert_video). Or clone it manually:
cd ComfyUI/custom_nodes
git clone https://github.com/ProGamerGov/ComfyUI_pytorch360convert_video
The only real dependency is pytorch360convert, a small PyPI package that the install pulls in automatically. Restart ComfyUI and you'll find both nodes under the pytorch360convert/video category.
Finishing the job
The node deliberately stops at frames - you assemble the video yourself with FFmpeg:
ffmpeg -framerate 60 -i video_frames/sweep360_%06d.png -c:v libx264 -pix_fmt yuv420p sweep.mp4
Common gotchas: forget the FOV ratio and your "360 tour" looks like a funhouse mirror; set 60fps/5s and suddenly you're writing 300 files per image (drop to 30fps or 2-3 seconds if you're just previewing); and remember the frames go into a video_frames subfolder, not the output root. If the node's slow, that's the CPU render path - it trades speed for not touching your VRAM, which is usually the right trade for a tool like this.
Inputs (19)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | Input equirectangular images (BHWC tensor). | |
| output_dir | STRING | /tmp/ComfyUI/output | Where to save frames (video_frames subfolder added). |
| filename_prefix | STRING | sweep360 | Prefix for saved frames |
| width | INT | 1920 | Output frame width (pixels). Should match fov_w:fov_h ratio for best results. |
| height | INT | 1080 | Output frame height (pixels). Should match fov_w:fov_h ratio for best results. |
| fps | INT | 60 | Frames per second. |
| duration_per_image | FLOAT | 5.00 | Seconds per 360° sweep (per input image). |
| total_duration | FLOAT | 0.00 | Total duration for all images (overrides duration_per_image if >0). |
| fov_h | FLOAT | 120.00 | Horizontal FOV (degrees). Should match width:height ratio for best results. |
| fov_w | FLOAT | 100.00 | Vertical FOV (degrees). Should match width:height ratio for best results. |
| speed_profile | COMBO | constant | Yaw speed profile. |
| interpolation_mode | COMBO | bilinear | Sampling mode for equirectangular to projection. |
| vertical_mode | COMBO | none | Vertical movement mode. Only used if vertical_mode is not set to None. |
| vertical_amplitude_deg | FLOAT | 15.00 | Amplitude in degrees for vertical motion. Only used if vertical_mode is not set to None. |
| vertical_pattern | COMBO | sine | Pattern for vertical motion. Only used if vertical_mode is not set to None. |
| vertical_pole_fraction | FLOAT | 0.50 | Fraction of frames for separate pole sweep. Only used if vertical_mode is not set to None. |
| start_yaw_deg | FLOAT | 0.00 | Starting yaw angle (degrees). |
| end_yaw_deg | FLOAT | 360.00 | Ending yaw angle (degrees). |
| save_format | COMBO | png | Image format for saved frames. |
Outputs (0)
No outputs