TechEarl

How to Blur Faces or Regions in a Video with ffmpeg

Blur a fixed region in a video with ffmpeg using crop, boxblur, and overlay, and blur moving faces automatically with deface. The honest note: ffmpeg alone has no face tracking.

Ishan Karunaratne⏱️ 9 min readUpdated
Share thisCopied
Blur a fixed region in a video with ffmpeg crop, boxblur, and overlay, blur moving faces automatically with deface, and pixelate as an alternative.

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:

bash
ffmpeg -i in.mp4 -vf "split[base][region];[region]crop=200:200:50:50,boxblur=10[blur];[base][blur]overlay=50:50" out.mp4

That 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:

bash
ffmpeg -i in.mp4 -vf "split[base][region];[region]crop=200:200:50:50,boxblur=10[blur];[base][blur]overlay=50:50" out.mp4
  1. split[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 with split first. [base] is the untouched frame the overlay sits on; [region] is the copy that gets cropped and blurred.
  2. crop=200:200:50:50 cuts a 200x200 pixel rectangle out of [region], with its top-left corner at x=50, y=50. The order is crop=width:height:x:y. This crop is what gets blurred, so size and place it over the thing you want to hide.
  3. boxblur=10 blurs 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. (boxblur applies the box twice by default, so even a modest radius smears hard.)
  4. overlay=50:50 pastes 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:

bash
ffmpeg -i in.mp4 -vf "boxblur=10:enable='between(t,2,8)'" out.mp4

To 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:

bash
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.mp4

Pixelate 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:

bash
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.mp4

Same 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):

bash
pip install deface
deface in.mp4

That writes in_anonymized.mp4. Useful options:

bash
# 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

Sources

Authoritative references this article was fact-checked against.

Tagsffmpegblur facesboxblurvideo anonymizationdefaceCLIprivacy

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts

How to Reverse a Video with ffmpeg

Reverse a video with ffmpeg using the reverse filter for picture and areverse for sound. Why you must write to a new output file, and why you trim before you reverse.

How to Crop a Video with ffmpeg

Crop a video with ffmpeg's crop filter: crop=w:h:x:y from the top-left origin, centered crops with in_w/in_h expressions, square crops for social, and cropdetect to strip black bars automatically.

How to Extract Audio From a Video with ffmpeg

Pull the audio out of a video with ffmpeg: copy the stream untouched when you just want to demux (fast, lossless), or re-encode to MP3, AAC, or WAV when you need a different format. Plus how to check the source codec first and grab a single segment.