ffmpeg -i in.mp4 -c:v libx264 -crf 28 -preset fast out.mp4 compresses a video to MP4, trading a bit of quality for a much smaller file — CRF is the dial, and 18–28 is the only range worth remembering. This also covers the CRF scale in real numbers, batch-converting a folder, and the step most guides skip: checking duration and codecs before an hour-long re-encode.
1. What's actually inside the file
$ clai show me the duration of this video→ ffprobe -v error -show_entries format=duration -of csv=p=0 in.mp42.000000
ffprobe ships with ffmpeg and doesn't re-encode anything. Before you start a conversion that might run for an hour, look at what you're actually working with.
2. Compress it, controlling quality
$ clai compress this video, quality matters more than size→ ffmpeg -i in.mp4 -c:v libx264 -crf 28 -preset fast out.mp4
On the test clip, the source was 13074 bytes and the output came out at 10861 bytes. CRF is a quality scale from 0 to 51, where lower means better and bigger. The range worth knowing is 18–28: 18 is visually indistinguishable from the source, 23 is a solid default, 28 is noticeably softer but still fine for most uses.
3. Shrink the resolution when compression alone isn't enough
$ clai compress it harder and scale the height down to 144 pixels→ ffmpeg -i in.mp4 -vf "scale=-2:144" -crf 30 small.mp4
Same clip, now 8130 bytes against the original 13074. The -2 in the width means "work it out yourself, keep the aspect ratio, and round to an even number" — codecs require even dimensions, and that's exactly where half the ffmpeg one-liners online fall over.
4. Change the container without touching the content
$ clai move this video from mov to mp4 without re-encoding→ ffmpeg -i input.mov -c copy output.mp4
-c copy copies the streams as they are — seconds instead of minutes, no quality loss, as long as the codecs are compatible with the new container. For mov to mp4, they usually are.
5. Process an entire folder
$ clai convert every mov in this folder to mp4, keep the names→ for f in *.mov; do ffmpeg -i "$f" -c:v libx264 -crf 23 "${f%.mov}.mp4"; done
${f%.mov} strips the extension. The quotes around $f aren't optional — skip them and the first filename with a space in it breaks the loop.
6. Cut a clip without re-encoding
$ clai cut a one-minute clip starting at 30 seconds→ ffmpeg -ss 30 -i input.mp4 -t 60 -c copy clip.mp4
-ss before -i is fast because ffmpeg seeks instead of decoding. With -c copy the cut lands on the nearest keyframe, so the start can drift by up to a second. For frame accuracy, drop -c copy and pay for the re-encode.
Gotchas
-presetchanges speed, not quality.ultrafastencodes fast into a bigger file,slowdoes the opposite. At the same CRF it barely affects quality.- Audio gets re-encoded silently. If you don't mention
-c:a, ffmpeg decides for you. Add-c:a copywhen the audio doesn't need touching. - CRF doesn't mean the same thing across codecs. For libx265, the same number buys more quality: CRF 28 on x265 is roughly CRF 23 on x264.
Related questions
Which CRF should I use? Start at 23. File too big — go to 28. Archiving something that shouldn't degrade — use 18.
Why is ffmpeg better than an online converter? The clip never leaves your machine, there's no size cap, and one command handles a whole folder.
How do I speed up encoding? Use a hardware encoder: -c:v h264_nvenc on NVIDIA, -c:v h264_videotoolbox on macOS. Much faster, slightly worse quality at the same bitrate.
See also
- Renaming hundreds of files: from for loops to plain English
- Compress this directory and upload it to S3
- From one-liner to checked-in script
CliAI writes the right ffmpeg flags for whatever you describe, CRF and scale filter included. Install it in one line.