Frame Chooser, mostly. A pause did not survive a workflow load: LiteGraph clears a graph by removing every node, so undo, a tab switch, Clear Workflow and opening another file all fired the teardown a deleted node uses to release its pause, and killed a run that was still going. That now only fires for a real deletion. Answering "keep all" wrote the batch out as 1,2,...,N into pick_list, so the next run dropped whatever the enumeration did not reach or failed outright on a shorter clip; it writes the empty answer it was given. And pick_list is only written back under "keep last selection" - it pre-answers the node, so filling it in automatically meant a chooser left at the default paused exactly once. Refine Mask: smooth applies only the change it made to the jaggy edge rather than binarizing everything, so an already-soft matte keeps its alpha (binary masks stay bit-identical), and blur now reaches the matting solve instead of being thresholded back out of the trimap. Frame Interpolate's copy path honours batch_size; it gathered every copied frame at once, which on a long clip at an integer multiple was a multi-gigabyte allocation on the frames device that no setting bounded. Subgraph execution ids are resolved by walking the chain instead of stripping the prefix, which could match an unrelated node with the same number. Status and runtime badges appear inside subgraphs again, and a subgraph pause renders on the node that actually paused. Also: the Custom colour scheme no longer strips every node's colour when its stored colour is unreadable; Drop Shadow and Pad Image name their own widget for an unreadable colour instead of blaming Transform; a non-ASCII token and a non-object JSON body answer 400 rather than throwing a 500 and stranding the pause; pick_list rejects Unicode digits, which used to raise during validation or silently read as a frame nobody typed. Tooling: validate_nodes parses NODE_MODULES rather than matching it anywhere in the text, and an unregistered module is an error - it used to exit 0 printing nothing. It also refuses mapping keys declared outside nodes/, which is how the registry fixtures came to be advertised to ComfyUI-Manager as installable nodes; they are .py.txt now. And the video test no longer leaves ComfyUI on sys.path, which was flipping every fail-soft seam for whatever ran next.
4.6 KiB
Frame Chooser
Pauses the running graph and turns the node into a clickable filmstrip of every incoming frame. Pick the frames to keep, press Keep selected, and the graph resumes with just those frames — always in their original order.
Controls
-
frames: A BHWC image batch, commonly the frame output of a video loader.
-
behavior:
always pausestops every run until you answer.keep last selectionre-applies this node's previous answer immediately and only pauses when no previous answer fits the current batch. -
preview_max_size: Longest edge of the filmstrip thumbnails. Smaller values encode and load faster; the full-resolution frames are untouched.
-
timeout_seconds: How long a pause waits before on_timeout answers for you.
0waits forever. While armed, the panel header counts down the seconds left. -
on_timeout: What an expired countdown does —
keep all,keep first,keep last, orcancel(interrupts the run like the stop button). Ignored while timeout_seconds is0. -
pick_list: One-based frame numbers, e.g.
1,4,9(commas or spaces). When filled, the node applies them immediately — no pause, no filmstrip — and the run can cache like any ordinary node. Clear it to make the node pause again. A number outside the batch fails the run instead of guessing.Under keep last selection, answering a pause fills this widget in for you with the kept indices, so the next queue reproduces the same choice headlessly. Under always pause nothing is written here: a filled
pick_listpre-answers the node, so writing one back would answer every later queue on its own and quietly retire the setting you chose. Keeping all frames writes an empty list, not an enumeration of the batch — the answer stays "keep everything" however long the next clip is.
While paused
- Click thumbnails to toggle them; the header counts the selection, and ALL / NONE flip the whole filmstrip at once.
- Keep selected resumes with the chosen frames. Keep all resumes with every frame — an empty selection deliberately means keep-all, so a quick "just continue" can never produce an empty batch.
- Cancel interrupts the run exactly like ComfyUI's stop button. Interrupting the queue also releases the pause.
- The controls grey out while an answer is on its way, so a doubled Enter or click cannot send it twice; a reply that lands after the pause is already over is ignored rather than reported as a failure.
- Reloading the page does not lose the pause: when the graph finishes loading, the panel re-fetches every still-waiting chooser from the server and re-renders its filmstrip (countdown included).
- A pause that starts out of sight — another browser tab, another workflow, or the node scrolled off the canvas — raises a toast naming the node and briefly highlights the waiting workflow tab. One notice per pause; a filmstrip you can already see stays quiet.
- The first moments after the filmstrip appears ignore clicks, so a click meant for the canvas cannot answer a pause that popped up under the cursor.
Keyboard
Active while the panel has focus — it takes focus when the pause opens, and a click anywhere on it returns focus. Keys typed into a text field are left alone.
| Key | Action |
|---|---|
1-9 |
Toggle that frame |
A |
Select all |
N |
Select none |
Enter |
Keep selected |
Escape |
Cancel the run |
Outputs
- frames: The kept frames as a BHWC batch, in source order.
- count: How many frames were kept.
- indices: The kept one-based indices, comma-joined (
1,4,9).
Thumbnails are written to ComfyUI's temp folder and disappear with its normal
cleanup; answers travel over a local /ausboss/frame_chooser route. The last
selection is remembered per node id for the current server session only. Each
pause has a one-use token, so an older panel cannot answer a later pause that
reuses the same node id.
One answer per pause
Several things can end the same pause: a second browser tab, Escape chasing
Enter, the countdown expiring in the instant an answer arrives, or the queue
being stopped. The server settles that on the way in — the first one to reach
the pause decides it, and every later attempt is refused rather than allowed
to overwrite the decision. So a cancel that lands behind a keep cannot stop a
run that is already continuing, an expired timer cannot discard the answer you
just gave, and the panel that lost never claims it was the one that counted.
Whichever way the pause went is broadcast to every open tab, which is what
releases the other panels and fills in pick_list.