inframes 0118 950 7617

Compressing video for the web with ffmpeg

A step-by-step guide for Windows. No prior command line experience needed

Video files that come straight out of a camera or a recording tool are usually far larger than they need to be for a website. This guide shows you how to shrink one down, typically by 70 to 85 per cent, without a visible drop in quality.


Step 1: Download ffmpeg

  1. Go to https://www.gyan.dev/ffmpeg/builds/
  2. Under the heading release builds, click the link for ffmpeg-release-essentials.zip (or ffmpeg-release-essentials.7z if you have 7zip installed)
  3. Save the file to your Downloads folder

The ZIP download is currently a little over 100MB.


Step 2: Install it

There is no installer. You just unzip the folder and put it somewhere sensible.

  1. Open your Downloads folder and find the zip file you just downloaded
  2. Right-click it and choose Extract All
  3. In the box that appears, delete whatever is there and type: C:\
  4. Click Extract

You will now have a folder inside your C: drive with a long name, something like:

C:\ffmpeg-7.1-essentials_build
  1. Rename that folder to simply ffmpeg

To rename it: open your C: drive in File Explorer, click once on the folder, press F2, type ffmpeg and press Enter.

You should end up with this:

C:\ffmpeg

And inside it, a folder called bin containing three files: ffmpeg.exe, ffplay.exe and ffprobe.exe.

Why C:\ffmpeg? Short paths with no spaces in them cause the fewest problems on the command line. Avoid putting it in Program Files, Documents or anywhere with a space in the name.


Step 3: Open the command line

  1. Press the Windows key on your keyboard
  2. Type cmd
  3. Press Enter

A black window opens with a flashing cursor. This is the command line, sometimes called Command Prompt.


Step 4: Go to the ffmpeg folder

Type this and press Enter:

cd C:\ffmpeg\bin

The text at the left of the cursor should change to C:\ffmpeg\bin>. That tells you where you are.

You only need to do this once each time you open a new command window.


Step 5: Compress the video

Copy the command below, replacing the two file paths with your own.

ffmpeg -i "C:\path\to\your-video.mp4" -c:v libx264 -preset slow -crf 23 -pix_fmt yuv420p -c:a aac -b:a 128k -movflags +faststart "C:\path\to\your-video-web.mp4"

To paste into the command line: right-click inside the black window. That pastes whatever is on your clipboard. Then press Enter to run it.

To get the path of your video easily: find the file in File Explorer, hold down Shift, right-click it, and choose Copy as path. That copies the full path with quote marks already around it, ready to paste.

The first path is the video you have. The second is the new, smaller one that ffmpeg will create. Give the new one a different name so you do not overwrite your original.

What happens next

A lot of text scrolls past. That is normal. Near the bottom you will see a line that updates continuously, showing the frame number and the time it has reached. When it stops and you get the C:\ffmpeg\bin> prompt back, it has finished.

A one minute video takes roughly one to three minutes. A ten minute video could take half an hour.


Step 6: Check it worked

Two things are worth checking.

Check the file size

Find the new file in File Explorer and look at its size against the original. A good result for a one minute 1080p video is somewhere between 5 and 15MB.

Check it is ready for streaming

Video files store their index in a section called the moov atom. For a video to start playing straight away on a website, that index needs to sit at the front of the file. If it is at the back, the viewer has to download the whole thing before anything appears, which is particularly noticeable on phones.

Run these two commands, one after the other. Wait for the first to finish before running the second.

ffprobe -v trace "C:\path\to\your-video-web.mp4" 2> trace.txt
findstr /i "moov mdat" trace.txt

You will get a handful of lines back. Look at the first and last of them.

Good result: the line mentioning moov appears above the line mentioning mdat.

type:'moov' parent:'root' sz: 62985 40 8521951
...
type:'mdat' parent:'root' sz: 8458926 63033 8521951

That is what you want. The index is at the front and the video is ready to publish.

Bad result: mdat appears first. Something went wrong with the -movflags +faststart part of the command. See the troubleshooting notes below.

Watch it

Finally, open the new file and watch it through at full screen size. Pay attention to any section with a lot of movement, as that is where compression problems show up first. If it looks fine, you are done.


Quick reference

Once you are comfortable, this is the whole job in three commands:

cd C:\ffmpeg\bin
ffmpeg -i "INPUT.mp4" -c:v libx264 -preset slow -crf 23 -pix_fmt yuv420p -c:a aac -b:a 128k -movflags +faststart "OUTPUT.mp4"
ffprobe -v trace "OUTPUT.mp4" 2> trace.txt && findstr /i "moov mdat" trace.txt

Adjusting the quality

The -crf 23 part of the command controls quality. It works backwards to what you might expect:

ValueResult
-crf 20Higher quality, larger file
-crf 23Good default for most web video
-crf 26Lower quality, smaller file

If your compressed video looks soft or blocky, run it again with -crf 20. If it is still bigger than you would like and quality is not critical, try -crf 26. Change nothing else.

Always compress from your original file, never from an already-compressed one. Each round of compression loses a little quality permanently.


Reducing the size of the picture

If your video will only ever be shown in a small window on a page, shrinking the picture saves far more than any quality setting will.

First, check what size it is now

ffprobe -v error -show_entries stream=width,height -of csv=p=0 "C:\path\to\your-video.mp4"

That returns two numbers: the width, then the height. Write them down, because everything below depends on them.

Then pick a side and give it a smaller number

Add -vf scale= to the command, with the width first and the height second. Put -2 in place of whichever side you are not setting, and ffmpeg will work that one out for you and keep the proportions correct.

To cap the height:

-vf scale=-2:1080

To cap the width:

-vf scale=1080:-2

The only rule is that the number you give must be smaller than that side currently is. If you cap a side at a number it has already reached or passed, nothing happens and your file comes out the same size as before.

There is no separate rule for widescreen or vertical video. Look at the two numbers from the check command, decide which side you want to bring down, and give it a lower value. Either side works, and the result is the same picture either way.

Here it is in a full command, capping the height at 1080:

ffmpeg -i "INPUT.mp4" -c:v libx264 -preset slow -crf 23 -vf scale=-2:1080 -pix_fmt yuv420p -c:a aac -b:a 128k -movflags +faststart "OUTPUT.mp4"

What the proportions do

The -2 means “work this dimension out from the other one, and round to an even number”. The picture is never stretched or squashed. Capping the height at 1080, for example:

Original sizeBecomes
3840 x 2160 (4K widescreen)1920 x 1080
1920 x 1080 (widescreen)unchanged, already 1080 tall
1440 x 1080 (older 4:3)unchanged, already 1080 tall
1080 x 1920 (vertical phone video)608 x 1080

Note the two rows where nothing happens. Those files were already at the cap. That is the most common reason a scaling command appears to do nothing.

Some useful sizes

CapGood for
1080Full width on a page, or a large embed
720Most embedded video
540Small embeds and thumbnails

One size rule to be aware of

This type of video needs both its width and its height to be even numbers. Virtually every camera and recording tool produces even dimensions anyway, so this rarely comes up. If you do hit an odd one, ffmpeg will stop with a message about the width or height not being divisible by 2. Add this to fix it:

-vf scale=-2:-2

That rounds both dimensions to the nearest even number and leaves everything else alone.

Does the shape of the video matter otherwise?

No. The compression command works for any resolution and any shape of video. Nothing in it assumes a widescreen picture. The quality setting is a target for how the video should look, not a target file size, so the encoder simply aims for that quality at whatever dimensions it finds. A small video produces a small file, a large one produces a larger file, and you do not need to change anything between them.

A note on large videos

The larger the picture, the larger the finished file will be at the same quality setting, because there is simply more detail to describe. A 4K video at -crf 23 will produce a much bigger file than a 720p one at the same setting. That is the encoder doing its job properly, not a fault.

If a file comes out larger than you want, scale the picture down rather than pushing the quality setting higher. Fewer pixels at good quality almost always looks better than the same number of pixels squeezed harder.


When the file is already small enough

Not every video needs compressing. If the file size is already reasonable and the only problem is that it does not start playing promptly on the page, you can fix that on its own without touching the picture at all.

ffmpeg -i "INPUT.mp4" -c copy -movflags +faststart "OUTPUT.mp4"

-c copy means “pass the video and audio through untouched”. It only rewrites the index and moves it to the front of the file. It takes a second or two, the file size barely changes, and there is no quality loss whatsoever, because nothing is being re-compressed.

This is always worth trying first on a file that is already a sensible size. Check the result with the same moov atom check as before.

One restriction. You cannot combine -c copy with -vf scale. Copy means leave the video alone, and a filter means decode and change it. If you need to resize, you have to re-encode, and the full compression command is the one to use.


Troubleshooting

“‘ffmpeg’ is not recognized as an internal or external command”

You are not in the right folder. Type cd C:\ffmpeg\bin and press Enter, then try again. If that also fails, ffmpeg is not where you think it is. Open your C: drive in File Explorer and check that C:\ffmpeg\bin exists and contains ffmpeg.exe.

“No such file or directory”

Almost always a path problem. Use the Shift + right-click, Copy as path trick rather than typing the path out. Make sure the path has quote marks around it, especially if any folder name contains a space.

If the file is on a network drive such as Z: and the path looks correct, check you have not opened the command line as an administrator. Mapped network drives are not visible in an elevated window. Close it and open a normal one.

Nothing at all comes back from ffprobe

Check the output file actually exists first. If the compression step failed, there is nothing to inspect. Scroll back through the ffmpeg output and look for a line containing the word “Error”.

The two check commands ran as one and produced a strange file

Paste and run them separately, or join them with && as shown in the quick reference. Pasting two lines at once can cause the second command to be absorbed into the first.

The output is bigger than the original

Your source was already well compressed, so -crf 23 is asking for better quality than the file actually has. The encoder then spends effort faithfully reproducing compression marks that are already there. Phone footage, anything that has been through a social media site, and anything recorded as HEVC will all behave this way.

Try -crf 28, and scale the picture down as well. If neither helps enough, check whether the original genuinely needs re-encoding at all. If it is already a sensible size and only needs to stream properly, use the copy command in the next section instead.

The scaling did nothing and the size came out the same

The number you gave was not smaller than that side already was. Run the check command, look at the two numbers, and make sure the value you set is below the current one for the side you are capping. Remember the width comes first and the height second.

“Filtering and streamcopy cannot be used together”

You have used -c copy and -vf in the same command. They cannot both apply to the video, because copy means “do not touch the video” and a filter means “decode it and change it”. Pick one. If you need to resize, you must re-encode.

“width not divisible by 2” or “height not divisible by 2”

Your video has an odd number of pixels along one edge. Add -vf scale=-2:-2 to the command, just before -pix_fmt. See the section on picture size above.

“Permission denied” or the file will not save

You may be trying to write to a folder you do not have rights to, or the output file is open in another program. Close any video player and try saving the output to your Desktop instead.

It is taking a very long time

-preset slow deliberately trades time for a smaller file. If you are in a hurry, change it to -preset medium or -preset fast. The file will be slightly larger but the encode will be quicker.

Working over a network drive is also slow and occasionally unreliable. For large files, copy the video to your Desktop first, compress it there, then copy the result back.

Leftover files

If you see files called trace.txt or ffmpeg2pass-0.log in the C:\ffmpeg\bin folder, they are temporary and safe to delete.


Optional: running ffmpeg from anywhere

If you use ffmpeg regularly, you can avoid the cd C:\ffmpeg\bin step by adding it to your system PATH.

  1. Press the Windows key, type environment variables and open Edit the system environment variables
  2. Click Environment Variables
  3. In the lower box, find Path and click Edit
  4. Click New and type C:\ffmpeg\bin
  5. Click OK on all three windows
  6. Close any open command windows and open a fresh one

You can now type ffmpeg from any folder. Test it by opening a new command window and typing ffmpeg -version.