Nodes/ComfyUI-Majoor-OmniCam/OmniCam Director
ComfyUI Node

OmniCam Director

Stop dictating camera moves to a prompt, keyframe them in a 3D viewport

By MajoorWaldi·Created 23 days ago·Updated a day ago· 12
OmniCam Director
  • image
  • video
  • audio
  • scene_3d
  • solved_scene
  • motion_scene
  • playblast_video
  • audio
state_json{}
recording_path
card_asset
width1280
height720
fps24
duration_seconds5.00
render_mode

You've been here: you write "slow dolly-in, camera orbits right" into a video prompt and get back something that sort of moved. Video models are terrible at taking dictation about motion - and they all want to be told differently anyway. Wan's camera-control path wants real extrinsics, LTX wants 2D motion tracks, MiniMax wants a reference clip. The OmniCam Director is the authoring end of a pack that treats that mess as a translation problem: you compose the shot once in a real 3D viewport, and it hands the result downstream as a model-independent MotionScene.

Think of it as a mini shot-layout tool living inside ComfyUI, not a typical plumbing node. You get a live 3D viewport, keyframable cameras, drawable motion layers over the frame, camera cuts, and a playblast recorder. Most of what it does happens in the frontend while you work; the Python execute() only fires when you queue, compiling the whole editor state into the canonical scene that travels between OmniCam nodes.

The inputs you actually set

Load it and you mostly leave the graph inputs alone - the interface manages the scary ones (state_json, recording_path, card_asset) for you. The fields that matter when you first drop it in:

  • width, height, fps, duration_seconds - your authoring canvas: 1280×720 @ 24fps, five seconds by default. This is the grid you compose on, not a locked output size; the Monitor resamples to whatever the target model wants.
  • render_mode - how the viewport shows your scene (graybox, grid, wireframe, point_field, card_grid, beauty, and omni_ref for compositing over reference footage). Cosmetic, but pick omni_ref when you're matching a real clip.
  • image / video (optional) - reference stills or a proxy clip to compose against. Both sockets accept VIDEO or IMAGE, so a generator's IMAGE batch plugs straight in.
  • solved_scene (optional) - connect an OmniCam Extractor here to import a recovered camera move and keep editing it. Only the playblast camera comes across, and it imports each new solve once, then leaves your edits alone; unplug the cable to freeze what you've imported.

Outputs

  • motion_scene (OMNICAM_MOTION_SCENE) - the whole authored scene: cameras, objects, motion layers, cuts, timeline. This is the wire to the OmniCam Monitor.
  • playblast_video (VIDEO) - the recorded proxy of the shot. Reference-video profiles downstream need this; it's a motion reference, not a render.
  • audio (AUDIO) - associated audio, passed through.

How authoring works

Compose your opening frame, press I to insert a camera keyframe, move the playhead, reposition, key again. Space previews the shot; when a reference-video workflow needs it, record a playblast. Every camera keeps its own keyframed track, and the whole thing serializes into the MotionScene rather than a pile of prompts. If the playblast is stale relative to the scene, the Monitor will read PLAYBLAST OUTDATED - re-record before you ship it.

Install

It ships in ComfyUI-Majoor-OmniCam (same author as the Majoor Assets Manager and ImageOps packs). Requires ComfyUI 0.31+; there are no required Python packages and no build step - the web bundle is committed. Easiest is Manager → Custom Nodes Manager → search Majoor OmniCam → Install, then restart. Or:

cd ComfyUI/custom_nodes
git clone https://github.com/MajoorWaldi/ComfyUI-Majoor-OmniCam.git

Restart ComfyUI and the nodes land under Majoor › OmniCam. All three are flagged experimental, so don't harden a production workflow around a socket that hasn't frozen yet - the Director's Motion Tracks surface is the least settled part. scene_3d is a best-effort UI bridge that guesses your 3D node's mesh path from common widget names; if your 3D node isn't detected, it's the naming, not you.

CategoryMajoor/OmniCam

Inputs (13)

NameTypeDefaultDescription
state_jsonSTRING{}
recording_pathSTRING
card_assetSTRING
widthINT128064–4096
heightINT72064–4096
fpsINT241–120
duration_secondsFLOAT5.000.25–120
render_modeCOMBO7 options: omni_ref, graybox, grid, point_field, wireframe, card_grid, +1
imageoptVIDEO,IMAGEReference stills, or a clip sampled for them.
videooptVIDEO,IMAGEA proxy clip, or an IMAGE batch read at the node fps.
audiooptAUDIO
scene_3dopt*
solved_sceneoptOMNICAM_MOTION_SCENEA solved scene from OmniCam Extractor. Only its playblast camera is imported: motion layers, objects and cuts on the upstream scene are not merged. The Director imports each new extractor fingerprint once and then leaves your edits alone; disconnect the cable to freeze what you imported.

Outputs (3)

NameTypeDescription
motion_sceneOMNICAM_MOTION_SCENE
playblast_videoVIDEO
audioAUDIO