Directing
UBDirectingNode is Directing's old name — and a guided tour of how the video capture actually works
- acting
- Captured Video
Quick naming note, then the useful part. UBDirectingNode is the legacy class name for DirectingNode in the ComfyUI-scene-camera-action pack - from when the project was the Unboring 3D Studio (UB), before it became Scene Camera Action. It's the same class, kept registered so old graphs load. New work: add "Directing."
The useful part: if you've landed here, odds are you're either curious about how a ComfyUI node produces an actual video file, or you're staring at a capture error and want to know who to blame. This page is the mechanism tour, because Directing's capture pipeline is the most unusual thing in the pack - and knowing it is what turns "it randomly fails" into "oh, that's why."
The capture pipeline, end to end
Here's the mental model: the video is filmed in your browser, not rendered by Python. When you queue the graph:
- The backend validates that your Acting input actually carries recorded motion (a real trajectory, not just a connected node).
- It pokes the browser frontend over a WebSocket and waits - up to 40 seconds.
- The three.js widget rewinds the acting timeline, plays your camera cuts at 30fps, and records the WebGL canvas with the browser's MediaRecorder.
- The recorded WebM is uploaded to ComfyUI's server, which converts it to H.264 MP4 (
yuv420p,+faststart, QuickTime-compatible) ifffmpegis found. - The file lands in your ComfyUI
input/folder as3d_directing_record_<nodeid>.mp4(or.webmif ffmpeg was missing), and gets returned as aVIDEOoutput you can wire into a reference-to-video model.
Two details in the code explain quirks people hit. First, the node deliberately reports itself as always-changed, so it never gets cached out of a run - the capture must fire every single queue. Second, the 40-second handshake is the whole dependency on the browser being alive: there's no server-side renderer to fall back on.
Inputs and outputs (briefly)
Only two optional inputs: acting (the Acting node's motion - mandatory in practice) and directing_data (your camera-cut timeline, managed by the widget's visual editor). The single output is Captured Video of type VIDEO. The camera rigs (third-person, first-person, tracking-side, master-wide), the anti-collision Spring Arm, and the cut timeline are all inside the widget.
The errors, decoded
- "Directing canvas is disabled. Connect an Acting node and record motion first." - Acting has no recorded take. Record motion with WASD so a trajectory exists, then re-queue. This is the pack README's own FAQ entry, and it's the most common error by far.
- "No video file was generated." - the backend waited 40 seconds and the frontend never reported back. Almost always means the browser tab wasn't actually running the graph - an API-only queue, a closed/hidden tab, or the widget not being mounted. Keep the tab open and the graph visible while it captures.
- WebM instead of MP4 - not an error, just a missing
ffmpegon the system PATH. Install ffmpeg and the conversion kicks in. Some downstream video nodes are picky about MP4/H.264; most web tooling plays WebM fine, but don't be surprised when a workflow expects the mp4.
Install
ComfyUI Manager → search "Scene Camera Action", or:
cd ComfyUI/custom_nodes
git clone https://github.com/arturitu/ComfyUI-scene-camera-action.git
pip install -r ComfyUI-scene-camera-action/requirements.txt
Restart, then it's under scene-camera-action. Nothing else to fetch - but yes, the ffmpeg note above is a real system dependency for clean MP4 output.
There aren't many ComfyUI nodes that ask the browser to do the heavy lifting this way. It's a neat trick for a previz tool - your editing happens exactly where you can see it. Just remember the browser is the camera.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| actingopt | * | Acting motion connection from an Acting node | |
| directing_dataopt | STRING | Serialized camera cut timeline (managed internally) |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| Captured Video | VIDEO | — |