Nodes/ComfyUI-FunPack/FunPack Shot Camera
ComfyUI Node

FunPack Shot Camera

A camera operator made of regex, and that's the point

By digital-garbage·Created about a year ago·Updated about 13 hours ago· 20
FunPack Shot Camera
  • settings
  • text
  • status
◄text►
◄length124►
◄frame_rate25.00►
◄project►

MiniMax H3 doesn't take a paragraph. It takes a structured prompt - [Shot 1], [Shot 2], <Subject 1> tags, camera directions - and the model is unusually responsive to how that structure is written. Which means writing a good H3 prompt is a small directing job: does each shot have a camera move, is it pointed at the right thing, do the cut times add up to the clip length. FunPack Shot Camera does that pass for you. No language model involved, which is the whole design.

What it actually does

You hand it prompt text, a frame count and a frame rate. It finds the [Shot N] blocks, works out how many seconds each one gets from length / frame_rate, and rewrites them: cut times, views, camera moves, detail notes.

The clever part is picking what the camera should move toward. It runs a small spaCy tagger over the shot and chooses the most specific thing in it - the rules-only fallback kicks in when spaCy isn't installed, and spaCy is one of the pack's opt-in add-ons (switched on in Settings ▸ Modules, installed on the next start). A few things are deliberately excluded:

  • <Subject N> tags are never a target on their own. A part or belonging of one - "<Subject 1>'s hand" - is.
  • Anything named in most shots, or in the text before the first shot, is a constant, not a target. Your protagonist isn't something the camera should drift toward; they're what's in frame.
  • Sound text is left alone. "Music" and "score" aren't visual subjects.
  • Shots that already have a camera move are skipped - and the detector is fussier than a keyword match, because "tilts <Subject 1>'s head" and "pulls out a knife" are body movement, not camera work. It only counts when the camera does it.

Each behaviour is off until you switch it on in Settings ▸ Engine, so the node won't silently redecorate a prompt you're happy with.

Inputs and outputs

Required: text, length (frames - the tooltip is explicit that with the frame rate this is how long the shots have between them), and frame_rate. Get length right or the cut timing is wrong by whatever factor you were off.

Optional: settings, the FUNPACK_SETTINGS payload, so the studio's module switches reach the node; and project, a string naming the project - this is where focus infusion draws from, using words that project's own prompts keep returning to.

Outputs: text - the rewritten prompt, or the original - and status. When nothing is enabled, or there's no [Shot N] in the text, it returns the prompt unchanged with the status unchanged. That's how you tell "it chose not to" from "it ran and did something".

The node also remembers what it chose, which is what lets the taste modules learn from a rating later. It deliberately re-runs every time instead of being cached, for that reason.

Why rules instead of an LLM

Because a prompt rewriter that hallucinates is worse than no rewriter. A rules pass either finds a shot and adds a move, or it leaves the text alone - and if it throws, it logs the failure and hands the original text back rather than failing your run. You can't say that about a small language model doing free-form editing on your prompt.

The cost is that it's occasionally literal-minded - regex and a tagger picking nouns, not a director. Where it shines is the grind: twelve shots, none with a camera move, and you'd rather not write twelve.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/olivv-cs/ComfyUI-FunPack
pip install -r ComfyUI-FunPack/requirements.txt

Then restart and, if you want the good tagger, switch the spaCy add-on on in Settings ▸ Modules - the pack installs it on the next start rather than dragging it into requirements.txt. ComfyUI Manager works as well (search ComfyUI-FunPack).

Troubleshooting

Status says unchanged. Two causes: no [Shot N] markers in the text, or every relevant switch in Settings ▸ Engine is off. Both are by design, and neither is an error.

It rewrote a shot you'd already finished. That shot either had no camera language the detector recognised or no move at all. Fix by writing the move in H3's own vocabulary - "the camera pushes in" reads as a camera move, "push in" on its own is ambiguous enough that it may get treated as body movement. Run this node before your manual polish, not after.

Status reads left as written (<something>). The rewrite threw and it chose your prompt over the run. That's the intended failure mode; report it with the message.

Cut times look stretched. Check frame_rate matches what the sampler is generating at, and that length is frames.

CategoryFunPack/Conditioning

Inputs (5)

NameTypeDefaultDescription
textSTRING—
lengthINT1241–100000Frames of the video: with the frame rate, how long the shots have between them.
frame_rateFLOAT25.001–240—
settingsoptFUNPACK_SETTINGS—
projectoptSTRINGThe project being made: the words focus infusion draws on are the ones this project's own prompts keep returning to.

Outputs (2)

NameTypeDescription
textSTRING—
statusSTRING—