SolarWM Camera Attach
Give MiniMax H3 an actual camera with SolarWM Camera Attach
- model
- latent
- positive
- model
MiniMax H3 is a great open-weight video model and a terrible camera operator. You prompt it for a dolly-in and it gives you… whatever it feels like, because camera motion isn't an input - it's something the model has to guess from text. That's the gap SolarWM is attacking, and SolarWM Camera Attach is the node that closes it. Feed it the H3 model, your video latent and conditioning, tell it how far and how fast to orbit or dolly, and out comes a patched MODEL that's supposed to follow the trajectory you described.
Fair warning: this pack is early. SolarWM is a research project on training long-horizon video world models with explicit camera trajectories, and the README admits more features are waiting on the official project code. What ships today is a working skeleton - a camera-aware attention patch - not the full training pipeline. The node is days old with zero community signal yet; you're an early adopter, which makes you the beta tester.
How it actually works
The mechanism matters because it tells you what can and can't go wrong. SolarWM's trick is to bake the camera into the model's positional encoding: instead of inferring motion from a prompt, it attaches a fused projective transform - a "camera-aware PRoPE" - to the attention path, one matrix per camera frame.
Under the hood, SolarWMCameraAttach clones the loaded H3 model with model.clone() and builds an inline [F,4,4] orbit/dolly trajectory (a placeholder for the real SolarWM trajectory source). It computes a row plan mapping video latent frames to camera frames, then patches every DiT and token-refiner Attention.forward to apply those projective matrices to q, k, v and the attention output - only on the RoPE path, so the text-refiner blocks stay untouched. No comfy/ source file is modified - it's all ModelPatcher object patches ComfyUI snapshots around sampling. Bypass the node and you get stock behavior; that bypass is the A/B reference, so there's deliberately no enable switch.
The inputs that matter
The three floats are the whole show:
orbit_turns(-10 to 10, default 1) - how many full rotations the camera sweeps around the subject. Set it to 0 for no orbit, negative to spin the other way. Don't overthink left vs right - flip the sign when the spin comes out backwards.radius- the starting camera distance from the subject. Think orbit radius.radius_end- where the radius ends up. Less thanradius= dolly in (push toward the subject), greater = pull back. Equal values give a pure orbit; withorbit_turnsat 0, a shrinking radius becomes a clean push-in - the standard camera test.
Then the two context inputs beginners trip on:
latent- the H3 video latent. Not optional decoration: it drives the trajectory length, and the node refuses to run without a real[B,24,T,H,W]H3 latent.positive- your H3 conditioning, which supplies the text context length for the row plan. Also required, and it fails loudly if you feed it the wrong conditioning.
Everything hangs off the H3 video latent and conditioning from a MiniMaxH3ImageToVideo node - this won't work with a generic image latent. The single output, model, replaces the model feeding your BasicGuider → SamplerCustomAdvanced chain.
Installing and wiring it
Install is the usual two-liner:
cd ComfyUI/custom_nodes
git clone https://github.com/smthemex/ComfyUI_SolarWM_H3
# restart ComfyUI
ComfyUI Manager can also grab it (search "ComfyUI_SolarWM_H3" or "SolarWM"). There's no requirements.txt and no heavy Python deps - the pack lives on ComfyUI's own comfy.quant_ops and attention internals. The real dependency is the SolarWM adapter LoRA, which the README calls out:
ComfyUI/models/lora/adapter_model_comfy_new.safetensors
Grab it from the SolarWM-H3-ComfyUI HF repo. That adapter is what makes the model camera-aware; the orbit math just steers it. The example workflow stacks it as a second LoraLoaderModelOnly after an H3 turbo LoRA, on the H3 UNet + Qwen3-VL CLIP + dual VAE stack. Expect big VRAM even with the _pruned_int8 files the example uses.
Common gotchas
The one real trap is wiring the node in the wrong place or with the wrong source. It must sit between your LoRA-stacked H3 model and the guider, and both latent and positive have to come from the H3 video conditioning nodes - not some random latent lying around. A ValueError demanding "the H3 AV LATENT" or "the H3 positive CONDITIONING" means exactly that; check what feeds those inputs.
Don't expect the stock model to suddenly frame perfectly either - this steers a model that mostly still behaves like H3. If your shots look unpatched, check the adapter LoRA is loaded at strength ~1. Watch the console too: the node prints a row-plan summary and a "patched N Attention.forward" line when it engages, which is your proof it's active. One quiet caveat on the model side: if you're in the US, EU, UK or Korea, the MiniMax H3 Community License doesn't license you to run the local H3 weights - a node can't fix that.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| orbit_turns | FLOAT | 1.00-10–10 | — |
| radius | FLOAT | 1.000–100 | — |
| radius_end | FLOAT | 1.000–100 | — |
| latent | LATENT | — | |
| positive | CONDITIONING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| model | MODEL | — |