Nodes/ComfyUI-Majoor-ImageOps/〽️ Image Ops Camera Shake
ComfyUI Node

〽️ Image Ops Camera Shake

Handheld energy on demand — deterministic camera shake for stills and clips

By MajoorWaldi·Created 8 months ago·Updated 8 days ago· 11
〽️ Image Ops Camera Shake
  • fill_color
  • image
  • mask
  • image
  • mask
bypassfalse
translate_px12.0
rotate_deg1.50
zoom0.030
smoothing0.65
shake_frequency1.00
frame_length24
fps12.0
seed12345
filterbilinear
fill_modemirror
invert_maskfalse

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), and zoom (max zoom jitter around 1.0). shake_frequency sets how often the shake target changes - 1.0 means a new target every frame, lower values make the motion slower and more wander-y. smoothing interpolates between targets (0–0.98) so it's a smooth handheld glide rather than frame-to-frame static.
  • The length - frame_length is how many output frames you get when the input is a still image (the default 24 = one second at typical preview speeds). fps only drives preview playback speed; it doesn't change the data.
  • The edges - when you translate, you push content off-frame. fill_mode decides what shows up behind it: mirror (default) reflects the edges, transparent leaves holes, stretch squashes, expand grows the canvas, and color fills with fill_color. If you're comping the shaken result over something else, transparent plus 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.

Categoryimage/imageops

Inputs (15)

NameTypeDefaultDescription
bypassBOOLEANfalse
translate_pxFLOAT12.00–512
rotate_degFLOAT1.500–45
zoomFLOAT0.0300–1
smoothingFLOAT0.650–0.98
shake_frequencyFLOAT1.000.05–8How quickly the camera shake target changes. 1 = one target per frame; lower is slower, higher is more nervous.
frame_lengthINT241–4096Number of output frames when shaking a still image.
fpsFLOAT12.01–120
seedINT123450–18446744073709550000
filterCOMBObilinear3 options: nearest, bilinear, bicubic
fill_modeCOMBOmirror5 options: transparent, mirror, stretch, expand, color
fill_colorCOLOR#000000
invert_maskBOOLEANfalse
imageoptIMAGE,VIDEOImages/Video input.
maskoptMASK

Outputs (2)

NameTypeDescription
imageIMAGE
maskMASK