Optional Video (obvpm)
What should happen when nobody wired a video in
- input
- video
- present
Optional Video exists for one situation: a workflow where a video might be connected, and you want to decide in advance what happens when it isn't. An init clip you sometimes have. A "reuse this clip instead of generating one" path a collaborator will never use. A template you hand out where half the people will leave the video slot empty.
You could just leave the input unconnected and hope. This node makes that decision explicit, and it does it for VIDEO - the type ComfyUI's native video nodes pass around, so it sits directly on that wire.
The two-way decision
on_empty is the whole node, and it has two settings:
mute(the default) - the gate emits an execution blocker, and every node downstream of it is silently skipped. Not an error, not aNone: those nodes just don't run.bypass- the gate outputsNone, and a downstream node whose input is optional treats that as unconnected and handles the absence itself.
Those are genuinely different, and picking wrong is where people get burned. bypass is polite: it hands the problem to a consumer that has declared it can live without a video. Feed that None into a required input and you get an error instead. mute doesn't ask anyone: it kills the path.
Inputs and outputs
input is optional and accepts a VIDEO. on_empty is the enum above. Outputs are video - your value passed through, or blocked, or None, depending on what happened - and present, a boolean that is true when an input is connected.
present is the interesting one. It stays live even in mute mode, which means a muted value path can still drive logic: wire it into a Lazy Switch's boolean and the graph can take the "no clip, generate from scratch" branch while the video path is dead. That's the combination this node is built for.
One structural note: it's not an output node, so wiring it does nothing on its own. Something downstream has to be queued for this to execute.
Where it fits: mute, bypass, and lazy are three different things
ComfyUI offers three ways to not run part of a graph, and conflating them is the source of most "why did my branch vanish" confusion.
Mute and bypass act downstream of the gate. Lazy evaluation - the kind Lazy Switch nodes use - is the only one that saves the work upstream, because the unselected branch is never evaluated at all. This gate can't help with upstream cost: by the time it can object to a missing video, whatever fed it has already run. A clip loader upstream of a muted gate still loaded the clip. If the expensive thing is upstream, you want the pack's Lazy Switch (it works fine with one, and the boolean coming out of present is exactly what it wants).
And muting a path completely is a two-mechanism job: laziness alone can't stop a save or preview node, because every output node is an execution root. The pack's documentation is unusually clear about this, which is more than most gates manage.
Know the family, too: Optional Image, Optional Video, Optional Audio, Optional Latent and Optional Any (the wildcard, whose outputs are value and present). Same behaviour throughout - pick by the type on the wire. There's also Mute, driven by a boolean, and Required Model, which does the opposite of optional: it refuses to queue until a model is wired in, so the failure is loud at the gate instead of mysterious three nodes later.
Installing it
cd ComfyUI/custom_nodes
git clone https://github.com/chanon/comfyui-obvpm
Restart ComfyUI, or install through ComfyUI Manager by searching comfyui-obvpm. No extra Python dependencies - the pack ships an empty dependency list because everything it imports already comes with ComfyUI. The class id is VideoOptionalGate (obvpm); searching the node menu for obvpm finds the whole family at once.
This pack is new - 0.2.0 landed 2026-09-13 and there's no community track record yet - so if something looks off, the README's mute/bypass/lazy table is the fastest way back to confidence.
Common issues
Nothing happened and there's no error. You're in mute, and the branch was skipped by design - that's what an execution blocker looks like. If you want a visible failure instead of a silent skip, that's a different node, not a different setting.
An error downstream about a missing video. You're in bypass and the consumer's input is required. Either switch that node's input to optional, or move to mute and accept that the branch disappears.
The upstream work still ran. Expected. The gate decides what happens downstream; it can't un-run a clip loader. Move the gate above the expensive node, or put a Lazy Switch in front of it.
A workflow saved with the old bare class id. All of this pack's node ids were renamed in 0.2.0 after a clash with another pack's Bundle node; old workflows are migrated automatically when opened. If a gate still won't run, delete it and create a new one - the README suggests exactly that if the migration leaves anything stuck.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| on_empty | COMBO | mute | What downstream sees when no input is connected: mute skips every downstream node, bypass outputs None. |
| inputopt | VIDEO | The value to pass through. May be left unconnected. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| video | VIDEO | The input passed through. When the input is empty: blocked (mute) or None (bypass). |
| present | BOOLEAN | True when an input is connected. Stays live even in mute mode. |