〽️ Image Ops Camera Shake
Handheld energy on demand — deterministic camera shake for stills and clips
- fill_color
- image
- mask
- image
- mask
You rendered a shot and it looks too clean - like it was locked off on a tripod when the scene calls for a handheld documentary vibe. That's the gap ImageOps CameraShake fills: it adds animated translation, rotation, and zoom jitter to an image or video batch, with a deterministic seed so the same input always gives the same shake. Part of the ComfyUI-Majoor-ImageOps pack, it's the kind of node that makes ComfyUI feel like an actual finishing tool rather than a place where images go to be born and then leave forever.
How it works
Under the hood it's a seeded pseudo-random camera path, smoothed and applied per frame. The controls break into three groups:
- The shake itself -
translate_px(max jitter in pixels),rotate_deg(max rotation jitter), andzoom(max zoom jitter around 1.0).shake_frequencysets how often the shake target changes - 1.0 means a new target every frame, lower values make the motion slower and more wander-y.smoothinginterpolates between targets (0–0.98) so it's a smooth handheld glide rather than frame-to-frame static. - The length -
frame_lengthis how many output frames you get when the input is a still image (the default 24 = one second at typical preview speeds).fpsonly drives preview playback speed; it doesn't change the data. - The edges - when you translate, you push content off-frame.
fill_modedecides what shows up behind it:mirror(default) reflects the edges,transparentleaves holes,stretchsquashes,expandgrows the canvas, andcolorfills withfill_color. If you're comping the shaken result over something else,transparentplus the returned mask is your friend.
seed makes it reproducible - same seed, same path, every run. That matters more than it sounds: when you're iterating on a video, you don't want the shake to change under you every time you touch another node upstream. There's a 🎲 button on the widget to randomize it when you do want variety.
What comes out
image (the shaken batch) and mask - the mask is the alpha of the moved content, so you can layer the shaken frame over a background with the holes intact instead of letterboxing everything with fill_color.
Where it shines
Two classic uses: adding a subtle handheld wobble to a too-stable AI video clip, and breathing life into a still - run a generated image through with frame_length 24 and a gentle translate, and suddenly you have a usable two-second loop for an animated preview. Keep the amounts small; this is a seasoning node. Crank translate_px to the hundreds and zoom near 1.0 and you get a shakycam panic shot, which is fun once.
Install and gotchas
ComfyUI Manager (search "ComfyUI-Majoor-ImageOps") or:
cd ComfyUI/custom_nodes
git clone https://github.com/MajoorWaldi/ComfyUI-Majoor-ImageOps
Restart, then hard-refresh the browser (Ctrl+F5 / Cmd+Shift+R) so the preview JS loads. No models, no extra deps.
The trap people hit: big translate with mirror fill looks like a smeared mirror at the edges - switch to transparent and comp it, or drop the translate and let rotation do the work. Rotation reads as "handheld" at surprisingly low values, so start at 1–2 degrees, not 10.
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| bypass | BOOLEAN | false | — |
| translate_px | FLOAT | 12.00–512 | — |
| rotate_deg | FLOAT | 1.500–45 | — |
| zoom | FLOAT | 0.0300–1 | — |
| smoothing | FLOAT | 0.650–0.98 | — |
| shake_frequency | FLOAT | 1.000.05–8 | How quickly the camera shake target changes. 1 = one target per frame; lower is slower, higher is more nervous. |
| frame_length | INT | 241–4096 | Number of output frames when shaking a still image. |
| fps | FLOAT | 12.01–120 | — |
| seed | INT | 123450–18446744073709550000 | — |
| filter | COMBO | bilinear | 3 options: nearest, bilinear, bicubic |
| fill_mode | COMBO | mirror | 5 options: transparent, mirror, stretch, expand, color |
| fill_color | COLOR | #000000 | — |
| invert_mask | BOOLEAN | false | — |
| imageopt | IMAGE,VIDEO | Images/Video input. | |
| maskopt | MASK | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |