ComfyUI Node

RB Command

Run ffmpeg and your own scripts from inside a ComfyUI workflow

By itribs·Created 4 days ago·Updated a day ago· 0
RB Command
  • input_0
  • stdout
  • stderr
  • exit_code
commandecho input: {input0} seed: {seed}
working_dir/tmp/ComfyUI/custom_nodes
executable/bin/bash
timeout30
seed0

ComfyUI ends where your terminal begins. Need to hstack two videos, thumbnail a batch, or hand a generated image to a Python script that doesn't have a node? Normally that's "save it, alt-tab, run the command, come back." RB Command (class RB_Command, from the comfyui-rb-command pack) pulls that step back inside the graph: it runs an arbitrary shell command as part of your workflow, lets you wire images, video, audio and text straight into it as inputs, and hands back stdout, stderr and the exit code as wireable outputs.

It's glue, and it's the kind of node that quietly disappears into your more elaborate pipelines - you install it for one annoying thing and end up using it everywhere: ffmpeg filters that don't exist as nodes, your own post-processing scripts, or ComfyUI as the middle of an automation chain.

How it works

Under the hood it's a subprocess that runs your command through /bin/bash (configurable), with three layers of substitution that make graph data usable inside the shell:

  • {placeholder} syntax in the command text. {input0}, {input1}, ... become the file paths of whatever you connected; {seed} becomes your seed value. Paths are auto-quoted with shlex.quote, so filenames with spaces and weird characters are handled for you.
  • Environment variables - $INPUT_0, $INPUT_ALL, $SEED, plus counts like $INPUT_IMAGE_COUNT - if you prefer scripting to string replacement.
  • Type conversion on the way in. An IMAGE tensor is flushed to a temp PNG, video inputs to a temp MP4, audio to WAV, plain strings/numbers pass through as text. Those temp files are deleted after the run, and the only real dependency cost is numpy/Pillow/scipy - all of which you almost certainly already have. No models to download, no heavy extras.

While the process runs, stdout and stderr stream live to the console and to a small output panel on the node (the pack ships a web extension for that). There's also a one-entry result cache: it hashes the command, seed, working dir, executable, timeout and input files' size/mtime, and skips re-executing if the exact same thing runs again.

The inputs and outputs that matter

  • command - a multiline string, the whole show. Default is a demo echo. Supports every placeholder above.
  • seed - plain INT with a control_after_generate toggle, so you can randomize it per run. Only matters if your command references {seed} or $SEED.
  • timeout - seconds (1–3600, default 30). The process gets killed if it exceeds this.
  • working_dir and executable - cwd for the command and the interpreter (/bin/bash by default).
  • input_0 - the first of up to 20 dynamic, any-type input slots. Connecting something spawns the next one automatically.
  • Outputs: stdout and stderr (both STRING) and exit_code (INT). Wire stdout into a text preview/display node to see it, or feed exit_code into a conditional to branch on success.

A typical ffmpeg job reads like:

ffmpeg -y -i {input0} -i {input1} -filter_complex "[0:v][1:v]hstack" combined.mp4

Note you do not add your own quotes around {input0} - the substitution is already shell-quoted, and double-quoting it backfires.

Installing

ComfyUI Manager is the easy route - search "comfyui-rb-command" (it displays as "RB Command") and install. Or the old-school way:

cd ComfyUI/custom_nodes/
git clone https://github.com/itribs/comfyui-rb-command.git
pip install -r requirements.txt

Then restart ComfyUI. No checkpoints, no config, no API key.

Where people get burned

  • The tools aren't bundled. This node runs commands; it doesn't ship ffmpeg or ImageMagick. If ffmpeg isn't on your PATH, the run fails with a non-zero exit in stderr - the first thing to check when "nothing happens."
  • Windows + /bin/bash. The default executable doesn't exist on a vanilla Windows box. Set executable to something you actually have (or install Git Bash), or the spawn itself fails.
  • The 30-second default timeout will bite you on real video encodes. Crank timeout up before running something long.
  • working_dir must exist - it raises a ValueError otherwise.
  • Caching can look like a bug. If you re-queue with an unchanged command and identical inputs, you get the cached result rather than a fresh run. That's the feature working as designed; change any input and the fingerprint changes. And because this isn't an output node, ComfyUI's normal graph cache also applies - if nothing it depends on changed, it may not re-execute at all.
  • It's arbitrary shell execution. Full stop. A command widget runs whatever's in it with your user's permissions - exactly the no-sandbox situation that's made custom nodes a malware vector in this ecosystem. Only use it in workflows you wrote yourself and trust; never load a shared workflow containing this node without reading its commands.

The pack is new and still early, but the mechanism is simple and the README is honest. If you keep hitting the "I just need to run one command" wall, this is a clean way through it.

Categoryutils/command

Inputs (6)

NameTypeDefaultDescription
commandSTRINGecho input: {input0} seed: {seed}Placeholders: {input0} {input_count} {input_all} {input_image_count} {input_video_count} {input_audio_count} {seed} Environment variables: $INPUT_0 $INPUT_1 $SEED $INPUT_COUNT $INPUT_ALL $INPUT_IMAGE_COUNT $INPUT_VIDEO_COUNT $INPUT_AUDIO_COUNT
working_dirSTRING/tmp/ComfyUI/custom_nodesWorking directory for command execution
executableSTRING/bin/bashShell interpreter to use (e.g. /bin/bash, /bin/sh, python3)
timeoutINT301–3600Timeout in seconds, process will be killed if exceeded
seedINT00–18446744073709550000Random seed, accessible via {seed} or $SEED
input_0opt*Dynamic input slot, connect any type (image, audio, video, text, etc.). Connecting triggers more slots up to 20

Outputs (3)

NameTypeDescription
stdoutSTRING
stderrSTRING
exit_codeINT