H.264 is a great codec, ofcourse it's been superceeded by it's more powerful brother H.265 but it's still very much in use and certainly will not be going away anytime soon, so there's no reason to abandon it yet.
Since the internet is full of guides for H.264, there's little to no point in me creating another one, instead we'll go through the process of creating a batch file which will give us a multi-use ability to convert any video we want into a high quality, or low quality it's your choice, video file using the H.264 codec, plus some audio, all using FFmpeg.
So first off we need a video to convert, any video will do but I'll be using Big Buck Bunnys MP4 video found here, I've actually gone for the 4K version but anything will do, and for the purpose of this guide I've renamed it to "bigBuckBunny.mp4".
Now lets create a new script:
ffmpeg -i bigBuckBunny.mp4 -c:v libx264 -crf 18 -preset:v veryslow -c:a aac -b:a 128k bugBuckBunny-converted.mp4
Now if you save that, (following the locations outlined here) and double click the batch file to run it, making sure you've moved the downloaded video into the same location as FFmpeg, it'll convert the video "bigBuckBunny.mp4" into "bigBuckBunny-converted.mp4".
But what's actually happening? I'm sure those of you who dable with FFmpeg will easily understand without me having to explain, but for those who wish to learn more, keep reading.
In the most basic of explainations, we're calling FFmpeg, telling it to take the video bigBuckBunny.mp4 and convert it into an MP4 file, yes it's already an MP4 so there is actually little use in doing this other than to learn, which is exactly what we're doing so don't worry.
In more detail
We're calling FFmpeg and telling it the source input -i
, is bigBuckBunny.mp4, this basically just means that that's the video we wish to transcode.
Next we're telling it which video codec to use -c:v
, short for -codec:video
and we want to use libx264
, which is the encoder for H.264.
-crf 18
this is the option for Constant Rate Factor, basically this controls the quality of the transcoded video, it ranges from 0 to 51, 0 being lossless and 51 being the absolute worst quality. A good range to work in is 18 - 28, it's entirely up to you on how much or little quality you want.
Next is the preset, -preset:v veryslow
, this is a preset of the libx264 encoder, a nice and easy way of controlling the speed of the encode and the compression, you can find more information regarding them here.
Now we need some audio, -c:a
, just like -c:v
this is short for -codec:audio
and as such tells FFmpeg which codec we want for the audio, in this case, I chose aac
, this is FFmpegs built in codec for, as I'm sure you've guessed, aac.
Next we choose the quality we want for our audio, -b:a
, short for -bitrate:audio
and here I chose 128k
, of course if you want lower or higher quality adjust acordingly.
At the end of it all, we tell FFmpeg where to save our file and what to call it.
If you need even more information on H.264 and FFmpeg, then go here.
But enough of explaining the basics!
That script wont get us very far, we need to edit it everytime we want a new video transcoded, either that or rename all of our videos to "bigBuckBunny.mp4" which is most impractical.
No we want something that will take a video, any video and simply do the work for us, what's the point in a script that makes life more difficult?
Step 1
So what we want to do is copy the script that I've handily created before.
@echo off
setlocal EnableDelayedExpansion
set _dir=%~dp0
set _vid=%~dpnx1
set _bitrate=8000k
%_dir%ffmpeg -ss 28 -i "%_vid%" -t 10 -c:v libx264 -preset:v placebo -b:v %_bitrate% -bufsize %_bitrate% -minrate %_bitrate% -pix_fmt yuv420p -r 30 -an -strict strict -movflags +faststart -vf scale='1920':'-1' -pass 1 -f mp4 -y NUL
%_dir%ffmpeg -ss 28 -i "%_vid%" -t 10 -c:v libx264 -preset:v placebo -b:v %_bitrate% -bufsize %_bitrate% -minrate %_bitrate% -pix_fmt yuv420p -r 30 -an -strict strict -movflags +faststart -vf scale='1920':'-1' -pass 2 -f mp4 "%~dpnx_conv.mp4"
endlocal
now this script is only useful for me and this site, so lets make some changes
Step 2
Quickly deleting almost all of the main content and leaving the important bits:
@echo off
setlocal EnableDelayedExpansion
set _dir=%~dp0
set _vid=%~dpnx1
endlocal
Step 3
Now, lets add in the command we created up above:
@echo off
setlocal EnableDelayedExpansion
set _dir=%~dp0
set _vid=%~dpnx1
ffmpeg -i bigBuckBunny.mp4 -c:v libx264 -crf 18 -preset:v veryslow -c:a aac -b:a 128k bugBuckBunny-converted.mp4
endlocal
Step 4
Almost there but still it's only as useful as it was at the start, so... not very.
What we need is a way of converting any video we drop onto it, so first we need to capture the video being dropped onto it, this is actually already covered with _vid=%~dpnx1
. When we drop a video onto the script, it's Drive, Path, Name and eXtension dpnx
are all stored into a variable called _vid
.
In Batch, %0 is the argument for the script itself and %1 to %9 are arguments for the script, dropping a video automatically assigns it as an argument for the script.
So now we've captured the dropped video, lets put it to use:
@echo off
setlocal EnableDelayedExpansion
set _dir=%~dp0
set _vid=%~dpnx1
"%_dir%ffmpeg" -i "%_vid%" -c:v libx264 -crf 18 -preset:v veryslow -c:a aac -b:a 128k "%~dpn1-converted.mp4"
endlocal
Note: I've also added in the "_dir" before FFmpeg.
Now with this final modification we're pretty much done, we've replaced the "bigBuckBunny.mp4" with the variable %_vid%
, so the input, is whatever we drop onto it and if you've noticed, the output is now replaced with %~dpn1-converted.mp4
. This tells FFmpeg to output our transcoded video into the same Drive, Path, using the same Name, with a new suffix of "-converted.mp4", so we end up with the exact same name as the video we dropped onto the batch file but simply renamed to include "-converted.mp4" at the end, this way we can easily tell which video we've just made.
And with that, we're done, one batch file that will convert any video you drop onto it, into an MP4 with the H.264 codec, no more re-making commands, no more re-writing or modifying scripts, just one file, drag and drop and you're done.