Nodes/ComfyTV/Z Defocus
ComfyUI Node

Z Defocus

Real bokeh on AI video — if you feed it a depth map

By jtydhr88·Created 3 months ago·Updated about 16 hours ago· 725
Z Defocus
  • video
  • depth_image
  • depth_video
  • video
force_run_token0
project_id
parent_output_id0
focus_depth0.50
focus_range0.15
max_radius16
layers8
shapedisc
highlight_boost0.00
invert_depthfalse

Z Defocus is the ComfyTV stage that fakes a real lens: it takes your clip plus a depth map, and blurs by depth - so the background gets a genuine bokeh while the subject stays sharp. It's the difference between an AI video that looks generated and one that looks shot on a cinema lens. This is the one node of the four worth installing ComfyTV for on its own.

The catch, and it's a real one: it needs a depth map. Unlike the pack's other FX stages, which just need a video, Z Defocus will refuse to run without one. That depth map is exactly what depth-estimation models produce - Depth Anything is the usual source, and the KB's take on it holds here: it's a single-image estimator that's become the ecosystem default, so you almost certainly already have a workflow that can emit one.

How it works

Per frame, it reads the depth map and computes a per-pixel circle of confusion: pixels whose depth falls inside focus_range around focus_depth stay sharp; everything else gets a blur radius scaled up to max_radius. The depth range is sliced into layers bins, each bin is blurred with a bokeh-shaped kernel (a true disc or a hexagon), and the slices are composited front-to-back so foreground stays in front of background - the "painter's algorithm" trick that real DOF compositors use. highlight_boost multiplies bright pixels before the blur, which is what makes hot speculars bloom into those soft, expensive-looking bokeh circles. If your depth convention is inverted (near objects dark, far objects bright), flip invert_depth.

This one genuinely renders: it decodes your video, processes every frame through torch, and re-encodes (PyAV, no extra install). It's the slowest of the four stages here, and the cost scales with max_radius × layers - those two are where you budget.

The inputs that matter

  • video - your clip (required, COMFYTV_VIDEO).
  • depth_image or depth_video - at least one is required, and the node says so explicitly: "Z Defocus needs a depth map - wire a depth image or depth video (e.g. from Depth Anything)." A static image works for a locked-off shot; use a depth video if the camera or scene moves.
  • focus_depth (0–1, default 0.5) and focus_range (0–1, default 0.15) - where the sharp plane sits and how wide it is. Tighten focus_range for a more aggressive shallow-DOF look.
  • max_radius (1–48, default 16) and layers (3–12, default 8) - bokeh size and depth-slice count. Higher = smoother but slower.
  • shape - disc or hex for the bokeh kernel. Hexagon is the anamorphic-ish flex.
  • highlight_boost (0–3) and invert_depth - the "make highlights glow" and "flip near/far" switches.

The single video output goes downstream like any other stage.

Install and gotchas

Same install as every ComfyTV node - ComfyUI Manager (search "ComfyTV") or git clone https://github.com/jtydhr88/ComfyTV into ComfyUI/custom_nodes/, full restart. No extra Python deps for the stage itself; the only model involved is whatever you use to produce the depth map (a Depth Anything checkpoint in the usual ComfyUI depth-preprocessor slot).

The two ways people get stuck: forgetting the depth map entirely (you'll get the hard error above - it doesn't silently no-op), and picking layers=12 + max_radius=48 and wondering why a short clip takes minutes. Start at defaults, dial focus_range down for the shot, and remember: near-white means close in standard depth maps, so if your subject ends up blurred and the background sharp, invert_depth is your first move, not your last resort.

CategoryComfyTV/VideoFX

Inputs (13)

NameTypeDefaultDescription
force_run_tokenINT00–2147483647Internal — bumped on Run to invalidate ComfyUI's input cache.
project_idSTRINGInternal — populated by the projectStore on the frontend.
parent_output_idINT00–2147483647Internal — lineage parent set by spawn handlers on the frontend.
focus_depthFLOAT0.500–1
focus_rangeFLOAT0.150–1
max_radiusINT161–48
layersINT83–12
shapeCOMBOdisc2 options: disc, hex
highlight_boostFLOAT0.000–3
invert_depthBOOLEANfalse
videooptCOMFYTV_VIDEO
depth_imageoptCOMFYTV_IMAGE
depth_videooptCOMFYTV_VIDEO

Outputs (1)

NameTypeDescription
videoCOMFYTV_VIDEO