You can't perform any filtering without losing quality when encoding to a lossy format, but you have some options.
Crop with your player
A possible solution would be to crop during playback, so you don't even need to re-encode. It is also useful to preview a crop.
This method will not create an output file. This will use your video player to crop while it is playing. See one of the other methods below if you want an output file.
With ffplay
and crop filter:
ffplay -vf "crop=480:270:200:100" input.mp4
With vlc
(or cvlc
):
vlc input.mp4 --crop=480x270+200+100
Or you could crop with the VLC GUI: Tools → Effects & Filters → Video Effects → Crop.
Accept some quality loss (you may not even notice a difference)
Give it enough bits and you may not be able to tell there is a quality difference:
ffmpeg -i input -vf "crop=480:270:200:100" -c:v libx264 -crf 17 -c:a copy ouput.mp4
See FFmpeg Wiki: H.264 Video Encoding Guide for more info.
Use a bitstream filter
The h264_metadata and hevc_metadata bitstream filters can set crop dimensions without modifying the video itself.
Note: Your player may not support this method.
Example for H.264 video:
ffmpeg -i input.mp4 -c copy -bsf:v h264_metadata=crop_left=100:crop_right=20:crop_top=10:crop_bottom=10 output.mp4
Sets the frame cropping offsets in the SPS. These values will replace the current ones if the stream is already cropped.
These fields are set in pixels. Note that some sizes may not be representable if the chroma is subsampled or the stream is interlaced (see H.264 section 7.4.2.1.1).
Use a lossless format
ffmpeg
can encode with several lossless encoders: ffv1, huffyuv, ffvhuff, utvideo, libx264 (using -crf 0
or -qp 0
). The output will be lossless but the output file will be huge.
Note: Your player may not support this method.
ffmpeg -i input.mp4 -vf "crop=480:270:200:100" -c:v ffv1 -c:a copy output.mkv
or
ffmpeg -i input.mp4 -vf "crop=480:270:200:100" -c:v libx264 -crf 0 -c:a copy output.mp4
If your input is MJPEG
Stream copy the individual images with ffmpeg
, crop them losslessly with jpegtran
, then remux them with ffmpeg
. This will result in no loss, but you will be restricted to the ancient MJPEG format.
ffmpeg
command.ffmpeg -i input.mp4 -filter:v "crop=480:270:200:100" -c:a copy -qp 0 output.mp4