Causal Forcing Generate (T2V / I2V)
81 frames, 2 steps, and a receipt for what happened
- runtime
- image
- video
- report
One video shape, and no knobs to argue with
832x480, 81 frames, 16 fps. That's three seconds of video, and there is no width, height, length or fps input on this node - the runtime hard-checks fps == 16 and builds 21 latent frames (Wan's VAE has a temporal stride of 4, so 1 + 4×20 = 81 RGB frames). Your prompt is used exactly as written too: no rewriting, no negative prompt, no CFG. For a 2-step distilled autoregressive model that's not a limitation so much as an admission - guidance is baked into the checkpoint.
The upshot is a node with four real decisions: which model, what prompt, what seed, and how many videos.
How it works
Causal Forcing distills Wan2.1-T2V-1.3B into an autoregressive model that emits frames one at a time, keeping a KV cache of clean context and updating it per frame. The paper's claim is a fix to Self-Forcing's training pipeline: a bidirectional teacher shouldn't supervise an autoregressive student, so Causal Forcing first fine-tunes the bidirectional base into an autoregressive model, uses that as the ODE-init teacher, then runs the same DMD stage. Causal Forcing++ extended it to 1- and 2-step frame-wise models (wan-video.md, distillation.md).
It is genuinely fast: cfpp_framewise_2step ran 7.05 s per video in the generator and 12.31 s end to end on an RTX 5090 (20.3 GB peak), and someone on a 3060 clocked 11 s for a 2-second clip via a different, repackaged route. And the community never really picked it up, for the reason the top comment on the release thread gave: very fast, but an obvious quality drop. You're trading fidelity for interactivity. If that's not the trade you want, run a normal Wan workflow instead.
Unlike the repackaged-checkpoint route, this node drives the official pipeline: it writes a schema-checked job file, starts runtime/cf_job.py with the runtime's own Python, and imports the pinned upstream code unmodified. Every generator tensor loads with strict=True instead of falling back to a partial load, and the runner counts generator forwards per video (65 for the 2-step model, 105 for the 4-step) and fails on a mismatch. Bit-identical output to the official inference.py for a given prompt and seed is the goal.
The inputs that matter
runtime comes from a Causal Forcing Runtime node; without one you get an error naming the config file, not a crash.
model has four choices, and the tooltips are the author's own: cfpp_framewise_2step is the default (2 steps per frame, 4 for the first), cf_framewise_4step is the original baseline, cfpp_framewise_1step is the 1-step model, and cf_chunkwise_4step generates a chunk of frames at a time and is text-to-video only. Be aware that the pack's own status table marks the 1-step and chunk-wise models as accepted but not run - the runner checks their schedules, but no real-weight result was published. The 2-step and 4-step pair is the tested path. Worth trying both: by eye the README reports the 4-step model moves the camera and subjects much more, the 2-step keeps steadier shots.
videos (1-4) is the one people underuse. It queues seeds seed, seed+1, seed+2… inside one runtime process. Model load is 35-42 s per job, so four videos in one job costs one load, not four.
image is optional and frame-wise only: it becomes the first frame, resized to 832x480 and VAE-encoded the way the official script does it. Pass it to a chunk-wise model and the node refuses with "image-to-video is only supported by the frame-wise models". I2V with the 4-step model is untested too.
Outputs, and how to wire them
video is a real ComfyUI VIDEO - and it's a list. Send it to a native Save Video node (mp4/h264) or you'll see nothing: this node isn't an output node, so with the video output unconnected ComfyUI has no result to produce. The shipped workflows keep videos=1 per Generate node and use two nodes when they want two videos.
report is a JSON string: job dir, wall seconds, model load time, upstream commit, versions, and per video the seed, frame count, generator forwards actually run, CUDA peak and sha256 of the MP4 and the latents. Wire it to Preview Any. That hash is the point of the pack - proof you got the run you think you got.
Install and troubleshooting
Install the pack (Manager → search "Causal Forcing", or clone https://github.com/hiroki-abe-58/ComfyUI-CausalForcing into custom_nodes), build the WSL2/Linux runtime per docs/SETUP.md - Python 3.10 venv, torch 2.8.0+cu128, the flash-attn 2.8.3 wheel, the pinned upstream commit - register it in ComfyUI/user/causalforcing.runtimes.json, restart, and run Causal Forcing Doctor first.
- Empty prompt is rejected rather than defaulted. So is
seed + videos - 1overflowing 2³¹-1. - Every job starts cold. No persistent worker in this release, so a slow queue is load time, not bad settings. Run 4 videos, not 4 jobs, when you're iterating on a prompt.
- Cancel and timeout work properly - the runner kills its own process group, so you don't end up with an orphaned GPU process and no free VRAM.
- The runtime is offline (
HF_HUB_OFFLINE=1): a missing weight file fails instead of quietly downloading 17 GB mid-job.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| runtime | CAUSALFORCING_RUNTIME | — | |
| prompt | STRING | Used as written (no prompt rewriting). | |
| seed | INT | 00–2147483647 | — |
| model | COMBO | cfpp_framewise_2step | cfpp_framewise_2step: Causal Forcing++ frame-wise 2-step (official checkpoint causal-forcing++/framewise-2step.pt, EMA): 2 denoising steps per frame, 4 for the first frame. | cf_framewise_4step: Causal Forcing frame-wise 4-step (official checkpoint framewise/causal_forcing.pt, EMA): the 4-step baseline. | cfpp_framewise_1step: Causal Forcing++ frame-wise 1-step (official checkpoint causal-forcing++/framewise-1step.pt, EMA): 1 step per frame, 4 for the first frame. | cf_chunkwise_4step: Causal Forcing chunk-wise 4-step (official checkpoint chunkwise/causal_forcing.pt, non-EMA weights as in the official command): text-to-video only. |
| videos | INT | 11–4 | Videos in this job (seeds seed, seed+1, ...), one runtime process. |
| imageopt | IMAGE | Optional first frame for image-to-video (frame-wise models only). Resized to 832x480 by the runtime, as in the official script. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| video | VIDEO | — |
| report | STRING | — |