To blur a fixed region of a video (a face, a license plate, a name badge) with ffmpeg, crop that region out, blur the crop, and overlay it back at the same coordinates:
ffmpeg -i in.mp4 -vf "split[base][region];[region]crop=200:200:50:50,boxblur=10[blur];[base][blur]overlay=50:50" out.mp4That single filtergraph does the whole job, and the rest of this page explains it, covers blurring moving faces (which needs detection, not ffmpeg alone), and the pixelate alternative. The one thing to be clear about up front: ffmpeg has no built-in face detection or tracking. The command above blurs a rectangle at coordinates you supply, so it only works when the subject stays roughly put. The moment the face moves, you need a detection tool feeding the boxes (covered below).
Blur a fixed region (subject does not move much)
This is the ffmpeg-only case, and it is the right tool when the thing you want to hide stays in one place: a fixed name plate, a whiteboard, a window into a neighbour's flat, a face on a locked-off tripod shot. The filtergraph reads as three steps:
ffmpeg -i in.mp4 -vf "split[base][region];[region]crop=200:200:50:50,boxblur=10[blur];[base][blur]overlay=50:50" out.mp4split[base][region]forks the input into two identical streams. ffmpeg cannot feed one stream into two filters by reusing a label; you have to duplicate it explicitly withsplitfirst.[base]is the untouched frame the overlay sits on;[region]is the copy that gets cropped and blurred.crop=200:200:50:50cuts a 200x200 pixel rectangle out of[region], with its top-left corner at x=50, y=50. The order iscrop=width:height:x:y. This crop is what gets blurred, so size and place it over the thing you want to hide.boxblur=10blurs that cropped rectangle. The number is the luma blur radius: higher is a stronger, mushier blur, lower is subtler. A value around 10 reliably obscures a face; bump it to 20 or more if the region is large and detail still shows through. (boxblurapplies the box twice by default, so even a modest radius smears hard.)overlay=50:50pastes the blurred rectangle back onto[base]at the same x=50, y=50 the crop was taken from. The two coordinate pairs must match, or the blur lands in the wrong spot.
The [base], [region], and [blur] in square brackets are named pads wiring the chain together. A common first attempt is to skip the split and write [in]...;[in]... reusing the input label twice; ffmpeg rejects that with "Simple filtergraph was expected to have exactly 1 input and 1 output", because a single labelled stream can only be consumed once. The split is what makes the fork legal. If your coordinates are off, the fastest way to find them is to grab one frame (ffmpeg -ss 5 -i in.mp4 -frames:v 1 frame.png) and read the pixel position of the region in any image viewer.
To blur the region only during part of the clip, put a timeline enable expression on the filter. The simplest case is blurring the whole frame for a window, which needs no crop or overlay at all. This blurs between the 2 and 8 second marks and leaves the rest untouched:
ffmpeg -i in.mp4 -vf "boxblur=10:enable='between(t,2,8)'" out.mp4To restrict the blur to a region and a time window, keep the crop-overlay graph and put the enable on the overlay instead, so the blurred patch is only composited during the window:
ffmpeg -i in.mp4 -vf "split[base][region];[region]crop=200:200:50:50,boxblur=10[blur];[base][blur]overlay=50:50:enable='between(t,2,8)'" out.mp4Pixelate a region instead of blurring
A heavy blur is sometimes still legible; a hard mosaic is not. Pixelate by scaling the cropped region down to a few pixels, then scaling it back up with nearest-neighbour sampling so the blocks stay sharp:
ffmpeg -i in.mp4 -vf "split[base][region];[region]crop=200:200:50:50,scale=20:20,scale=200:200:flags=neighbor[px];[base][px]overlay=50:50" out.mp4Same crop-and-overlay skeleton as the blur (the split fork, then composite back over [base]), but the middle of the chain is scale=20:20 (collapse the 200x200 region to 20x20, destroying detail) followed by scale=200:200:flags=neighbor (blow it back to its original size with chunky, non-interpolated blocks). Fewer pixels in the down-scale (scale=10:10) means bigger blocks and a more thoroughly destroyed region. ffmpeg also has a dedicated pixelize filter that mosaics the whole frame in one step; the scale-down/scale-up trick is what lets you confine the mosaic to a cropped region. Unlike a blur, a mosaic cannot be reversed by sharpening, which is why it is the safer choice for genuinely sensitive content.
Blur moving faces (you need detection)
Once the face moves around the frame, a fixed rectangle is useless, and stock ffmpeg cannot find the face for you. (ffmpeg does ship a facedetect filter, but it lives in the OpenCV integration and only exists if ffmpeg was built with --enable-libopencv. The default Homebrew and most distro packages are not, so facedetect simply is not a filter on the install you have. Even where it is compiled in, it only reports detection metadata, it does not blur anything. It is not the practical path.) You have two real options.
The practical one is deface, a free command-line tool that runs an ONNX face-detection model (CenterFace) over every frame and blurs each detected face automatically. It is a user-space Python tool, so install it with pip and run it with no sudo (running it as root only gives you root-owned output you then have to chown back):
pip install deface
deface in.mp4That writes in_anonymized.mp4. Useful options:
# Keep the audio track (deface drops audio by default), tune detection, use a solid box
deface in.mp4 --keep-audio --thresh 0.2 --replacewith solid -o out.mp4--thresh (default 0.2) is the detection confidence: lower it if faces are being missed, raise it if non-faces are being blurred. --mask-scale (default 1.3) grows the blurred ellipse so it covers the whole face including the hairline. --replacewith chooses the filter: blur (default), solid (a black box), mosaic, img, or none. For anything you are publishing for privacy reasons, prefer solid or mosaic over blur, for the same reason as the pixelate section: a blur can sometimes be partially reversed.
The other option is to drive ffmpeg yourself from a detection script: run a face detector (OpenCV, dlib, MediaPipe, or the same CenterFace model) over the frames, emit per-frame bounding boxes, and feed those coordinates into ffmpeg, either by generating a sendcmd command file that re-positions a boxblur/crop region frame by frame, or by compositing the blurred patches in your own pipeline. This is exactly what deface does internally, so reach for it only when you need to bolt face-blurring into a larger custom pipeline. For a one-off "hide the faces in this clip," deface is the answer and writing your own tracker is wasted effort.
A note on what ffmpeg can and cannot do
ffmpeg is a transcoder and a filter engine, not a computer-vision toolkit. Its boxblur, crop, overlay, delogo, and pixelize filters operate on coordinates and time windows you give it. It has no concept of "a face," so it cannot track one. Any "automatic face blur" you have seen built on ffmpeg has a detector in front of it producing the boxes; ffmpeg just applies the blur. Keep that boundary clear and the toolchain is obvious: fixed region or fixed time window, ffmpeg alone; moving subject, a detector (deface) plus ffmpeg under the hood.
FAQ
See also
- The ffmpeg command cheat sheet: convert, crop, trim, and compress video from the command line, with every common filter in one reference.
- Crop a video with ffmpeg: the full
crop=w:h:x:yfilter, centred crops, and removing black bars, the same filter this article uses to isolate a region. - Convert a video to grayscale with ffmpeg: another single-filter video edit, with the difference between desaturating and true single-channel gray.
Sources
Authoritative references this article was fact-checked against.





