If a video will not play or upload because it is not an MP4, FFmpeg can convert it. It reads almost any video format, including AVI, MKV, and MOV.

In the commands below, replace input.avi, input.mkv and the other example names with the path to your own file.

Codecs and Containers

  • Container (the file extension): .mp4, .mkv, .avi and so on. It is the “wrapper” that holds the video and audio.
  • Codec: the way the video or audio is compressed. For MP4, the standard choice is H.264 (libx264) for video and AAC for audio.

The main codecs used in an MP4 container are H.264 or H.265 (HEVC) for video and AAC for audio.

Basic Command

ffmpeg -i input.avi -c:v libx264 -c:a aac output.mp4
Option Meaning
-i input.avi The input file
-c:v libx264 Encode the video as H.264 (libx264)
-c:a aac Encode the audio as AAC
output.mp4 The output file name (the .mp4 extension sets the container)

Primary source: FFmpeg Wiki - H.264 Encoding Guide

Adjusting Video Quality (CRF)

-crf sets the video quality. A lower value gives higher quality and a larger file.

ffmpeg -i input.avi -c:v libx264 -crf 23 -c:a aac output.mp4
CRF value Quality guide Use case
18 Near visually lossless Archiving
23 Default. Good balance General use
28 Stronger compression File size priority
51 Lowest quality Almost never used

“A subjectively sane range is 17–28” — FFmpeg H.264 Guide

Adjusting Encoding Speed (preset)

-preset trades encoding speed against compression efficiency.

ffmpeg -i input.avi -c:v libx264 -preset slow -crf 22 -c:a aac -b:a 128k output.mp4
preset Speed Compression efficiency
ultrafast Fastest Low
fast Fast Somewhat low
medium Default Balanced
slow Slow High
veryslow Very slow Very high

A slower preset compresses more efficiently. But at the same CRF, quality and file size both change with the preset, and a slower preset does not always give a smaller file. Primary source: H.264 Guide - preset

Stream Copy (No Re-encoding)

If the input already has H.264 video and AAC audio, you can change only the container, without re-encoding.

ffmpeg -i input.mkv -c copy output.mp4
  • Advantage: finishes almost instantly and loses no quality
  • Note: it fails if the MP4 container cannot hold the input codec. In that case, use -c:v libx264 -c:a aac instead.

Specifying Audio Bitrate

ffmpeg -i input.avi -c:v libx264 -crf 23 -c:a aac -b:a 192k output.mp4
-b:a value Use case
96k Low quality, speech only
128k General video
192k Music / audio quality priority
320k Very high quality

Summary of Commonly Used Command Examples

ffmpeg -i input.avi -c:v libx264 -c:a aac output.mp4
ffmpeg -i input.mkv -c:v libx264 -crf 22 -preset slow -c:a aac -b:a 192k output.mp4
ffmpeg -i input.mkv -c copy output.mp4
ffmpeg -y -i input.avi -c:v libx264 -crf 23 -c:a aac output.mp4

In the last command, -y overwrites an existing output file without asking first. This is useful in batch scripts.

Troubleshooting

Unknown encoder 'libx264'

Cause: Your FFmpeg build does not include libx264. Solution: Install an FFmpeg build that includes libx264. On Windows, the Full build from gyan.dev is recommended. Some Linux packages leave it out, for example Fedora’s ffmpeg-free.

Output File Is Too Large

Raise the CRF value (28–32) to make the file smaller. A faster -preset does not make the file smaller at the same quality. To get close to a target file size, use 2-pass encoding: see Two-Pass Encoding.

Stream Copy Fails

-c copy works only when the output container can hold the input codecs. If it fails, re-encode with -c:v libx264 -c:a aac.