How to crop images and videos with FFmpeg
Use FFmpeg’s crop filter to keep a rectangular part of an image or each video frame.
For example, crop=200:200:50:50 keeps a 200×200 region starting 50 pixels from the left and
50 pixels from the top. Below, you will crop a JPEG and an MP4, check their dimensions, and
apply the image crop to a directory with Bash.
Prepare FFmpeg and your files
Run the examples in Bash on macOS or Linux. Install a build containing ffmpeg, ffprobe,
and the libx264 encoder using the platform links on the
FFmpeg download page. The commands were tested with
FFmpeg 9.0.1 on macOS and 6.1.1 on Ubuntu 24.04.
Check your installation:
ffmpeg -version && ffprobe -version && ffmpeg -hide_banner -h encoder=libx264
The last command should list the encoder’s capabilities. If it reports an unknown encoder,
install a build with libx264 before continuing.
Put an upright JPEG named input.jpg and an MP4 named input.mp4 in your working directory.
The image example needs at least 250×250 pixels; the fixed video crop needs at least
1280×720. The video examples assume ordinary SDR video with square pixels and no rotation
metadata. Cropping HDR or anamorphic footage needs additional color or aspect-ratio handling.
The single-file commands use -y: rerunning them replaces their named output files.
Choose a different output name to keep an earlier result, and keep output names distinct
from your inputs. -nostdin disables keyboard interaction so commands also work unattended.
See FFmpeg’s command options.
Choose the crop rectangle
The filter syntax is crop=width:height:x:y. Coordinates start at (0,0) in the top-left
corner; x increases rightward and y downward. Cropping removes pixels outside the
rectangle without resizing its contents.
For a rectangle that stays inside the input, use positive dimensions and nonnegative offsets,
with x + width no greater than the input width and y + height no greater than its height.
Check these bounds yourself: FFmpeg can adjust an out-of-bounds offset to make the rectangle
fit instead of reporting an error.
You can omit x and y to center the crop. On chroma-subsampled input, the filter normally
rounds coordinates and dimensions down to the subsampling grid. The examples below use even
values for the usual 4:2:0 format. FFmpeg’s
crop reference documents these defaults and
the exact option for crops that need odd coordinates.
Cropping images with FFmpeg
Crop the rectangle described above and save it as cropped.png:
ffmpeg -hide_banner -nostdin -y -pattern_type none -i input.jpg \
-vf "crop=200:200:50:50" -frames:v 1 -update 1 cropped.png
-frames:v 1 writes one image. PNG avoids another lossy JPEG encoding after the crop.
-pattern_type none makes the input filename literal, while -update 1 does the same for
the output filename. Those options also matter when a filename contains %03d, which
FFmpeg would otherwise treat as an image-sequence pattern. These behaviors are documented
in the image input options
and image output options.
Check the output dimensions with ffprobe:
ffprobe -v error -select_streams v:0 -show_entries stream=width,height \
-of csv=p=0:s=x cropped.png
This should print 200x200. Open the PNG too: dimensions alone do not tell you whether
you kept the intended subject.
Cropping videos with FFmpeg
Keep the top-left 1280×720 region in every frame of input.mp4:
ffmpeg -hide_banner -nostdin -y -i input.mp4 \
-map 0:v:0 -map '0:a:0?' -vf "crop=1280:720:0:0" \
-c:v libx264 -crf 18 -pix_fmt yuv420p -c:a aac -b:a 128k cropped.mp4
The output contains H.264 video and, when present, the first audio track encoded as AAC.
The quoted ? makes the audio mapping optional, so silent inputs work too. Additional
video tracks, audio tracks, and subtitles are omitted. See the
stream mapping documentation.
Cropping requires decoding and re-encoding the video, so -c:v copy cannot be combined
with this filter. -crf 18 is a quality setting for the lossy H.264 encode.
-pix_fmt yuv420p selects 4:2:0 output, which requires even width and height with this encoder.
Crop a centered square
For either landscape or portrait video, choose the smaller input dimension and round it down to an even number:
ffmpeg -hide_banner -nostdin -y -i input.mp4 \
-map 0:v:0 -map '0:a:0?' -vf "crop=w='trunc(min(iw,ih)/2)*2':h=ow" \
-c:v libx264 -crf 18 -pix_fmt yuv420p -c:a aac -b:a 128k square.mp4
Here, iw and ih are the input dimensions, and ow is the calculated crop width.
Leaving out x and y centers the square, subject to the chroma-grid rounding described
above. A 1920×1080 input produces 1080×1080 pixels. This is a fixed center crop, so a
subject near an edge can still be cut off.
Verify the video output
Inspect the dimensions and codecs using
ffprobe’s selected entries:
ffprobe -v error -show_entries stream=codec_type,codec_name,width,height \
-of json cropped.mp4
Expect an h264 video stream with width 1280 and height 720, plus an aac stream if
the input had audio. Replace cropped.mp4 with square.mp4 to check the square crop.
Play the result to check framing and sound throughout the clip.
Batch-crop JPEG images
Save this as crop-images.sh and run bash crop-images.sh from the directory containing
your JPEGs. It processes non-hidden files ending in lowercase .jpg in that directory,
using the same 200×200 crop at (50,50). Each input must meet the 250×250 minimum for
that rectangle.
#!/usr/bin/env bash
set -euo pipefail
shopt -s nullglob
images=(./*.jpg)
if (( ${#images[@]} == 0 )); then
printf '%s\n' 'No .jpg files found.' >&2
exit 1
fi
mkdir ./cropped
for image in "${images[@]}"; do
name=${image##*/}
ffmpeg -hide_banner -loglevel error -nostdin -y \
-pattern_type none -i "$image" -vf "crop=200:200:50:50" \
-frames:v 1 -update 1 "./cropped/${name%.jpg}.png"
done
The script requires a new cropped directory: if it already exists, mkdir fails and
the script stops before processing anything. Keep that directory’s results and choose
a new output directory in the script for another run. Outputs are PNGs in a subdirectory,
so they cannot become inputs on the next run.
Quoting and the ./ prefix handle spaces and leading hyphens in filenames; the image
options handle literal percent patterns on both sides. An empty directory produces an
error. If FFmpeg fails on an unreadable image or an undersized crop, the script stops;
files already written remain in cropped, so inspect any partial results before retrying.
