Xbox Controller Mapper @ vrch.ai
Drive ComfyUI with an Xbox pad instead of a mouse
- raw_data
- FULL_MAPPING
- LEFT_STICK
- RIGHT_STICK
- LEFT_TRIGGER
- RIGHT_TRIGGER
- A_BUTTON
- B_BUTTON
- X_BUTTON
- Y_BUTTON
- LB_BUTTON
- RB_BUTTON
- VIEW_BUTTON
- MENU_BUTTON
- LEFT_STICK_PRESS
- RIGHT_STICK_PRESS
- DPAD_UP
- DPAD_DOWN
- DPAD_LEFT
- DPAD_RIGHT
- XBOX_BUTTON
The Xbox Controller Mapper @ vrch.ai is the node that turns a $50 gamepad into a live input device for ComfyUI. It's the second half of the pack's gamepad story: a Gamepad Loader node (same pack) captures your controller through the browser's Gamepad API - no drivers, no external app, no serial setup - and this Mapper takes that raw JSON blob and breaks it into named, typed outputs you can wire straight into a workflow. It's the exact pipeline behind the pack's most-liked demo, real-time avatar control with Advanced Live Portrait, where moving the left stick tilts a face in the generated image.
And yes, the "no drivers needed" claim occasionally gets flak on Reddit because you do install custom nodes. But the thing it's contrasting with is legitimate: real gamepad support usually means a native plugin, a virtual joystick, or a separate mapping program. Here you plug in a controller, open ComfyUI in Chrome or Edge, and the browser does the rest.
How it works
The Gamepad Loader emits the controller state as a JSON blob into this node's raw_data input, then the Mapper does what a mapper is for: it normalizes all of that into discrete outputs. Turn on debug and you'll see the raw state flying by while you mash buttons - which is genuinely the fastest way to learn which output maps to which input.
The outputs you actually care about:
- LEFT_STICK and RIGHT_STICK -
FLOATlists (X/Y each), for axes like head pitch/yaw or camera pan. - LEFT_TRIGGER / RIGHT_TRIGGER -
FLOATpressure values, great for smooth, analog control like zoom or intensity. - A_BUTTON, B_BUTTON, X_BUTTON, Y_BUTTON, LB_BUTTON, RB_BUTTON, VIEW_BUTTON, MENU_BUTTON, LEFT_STICK_PRESS, RIGHT_STICK_PRESS, plus the four DPAD_ directions and XBOX_BUTTON - all
BOOLEAN, for discrete triggers like "switch prompt" or "advance frame." - FULL_MAPPING - the whole
JSONstate in one output, in case you'd rather parse it yourself or pipe it to a debug display.
This node is not an output node, so nothing stops here - the sticks and buttons are meant to feed float/bool values into whatever you're controlling.
Installing it
Same single-pack install:
cd ComfyUI/custom_nodes
git clone https://github.com/VrchStudio/comfyui-web-viewer
pip install -r comfyui-web-viewer/requirements.txt
Or install "ComfyUI Web Viewer" via ComfyUI Manager and restart. The mapper itself needs no models and no extra dependencies; the only hardware requirement is a browser that speaks the Gamepad API (Chrome, Edge, and Firefox all do).
Getting it working
Three things bite people every time:
- The page must be focused and the controller must send a signal first. Press a button on the pad after loading the workflow so the browser registers it; if you have multiple controllers, check the Gamepad Loader's device index.
- This node only works when the ComfyUI tab is the active tab. The browser Gamepad API is tied to page focus, and the same is true of the pack's keyboard nodes. Click back into the ComfyUI tab before you play, or the state goes stale.
- Real realtime means instant queue. The demo workflows set ComfyUI to Queue (Instant) mode so every input change triggers a fresh run. Without it you're just buffering inputs for a generation you have to kick manually.
For the full "drive a live portrait with a pad" recipe, grab the example_gamepad_nodes_002_live_portrait.json workflow from the pack repo - it wires the sticks into Advanced Live Portrait and is the best working reference for how to map these outputs.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| raw_data | JSON | [object Object] | — |
| debug | BOOLEAN | false | — |
Outputs (20)
| Name | Type | Description |
|---|---|---|
| FULL_MAPPING | JSON | — |
| LEFT_STICK | FLOAT | — |
| RIGHT_STICK | FLOAT | — |
| LEFT_TRIGGER | FLOAT | — |
| RIGHT_TRIGGER | FLOAT | — |
| A_BUTTON | BOOLEAN | — |
| B_BUTTON | BOOLEAN | — |
| X_BUTTON | BOOLEAN | — |
| Y_BUTTON | BOOLEAN | — |
| LB_BUTTON | BOOLEAN | — |
| RB_BUTTON | BOOLEAN | — |
| VIEW_BUTTON | BOOLEAN | — |
| MENU_BUTTON | BOOLEAN | — |
| LEFT_STICK_PRESS | BOOLEAN | — |
| RIGHT_STICK_PRESS | BOOLEAN | — |
| DPAD_UP | BOOLEAN | — |
| DPAD_DOWN | BOOLEAN | — |
| DPAD_LEFT | BOOLEAN | — |
| DPAD_RIGHT | BOOLEAN | — |
| XBOX_BUTTON | BOOLEAN | — |