FFMpeg Command Line (DOS CLI) Tricks


Today’s post is off topic from cybersecurity. I’ve been playing around with FFMpeg to batch convert some video and audio files and want to share some tricks I’ve learned for both FFMpeg and the Windows DOS command line.

While I was researching how to do some of these commands, I found a lot of conflicting advice that was for using Linux command lines, etc. so to be clear, this is for the Windows DOS command line only! I make no guarantees this will work on other systems.

Okay, the common scenarios I’m going to show you how to work with today include:

  1. Using FFMpeg to convert a video file to an H.264 video format while copying the audio as is
  2. Iterating through a folder of video files and converting them as in #1
  3. Using FFMpeg to show the video and audio codec information of a file
  4. Iterating through a folder of files to show the video or audio codec information of all the files
  1. Using FFMpeg to convert a video file to an H.264 video format while copying the audio as is

ffmpeg -i movie.mkv -c:v libx264 -preset slow -crf 17 -tune film -c:a copy converted-movie.mkv

Breaking this command down:

ffmpeg = call the program

-i = designate the input file

movie.mkv = this is the original source file that you want to convert

-c:v = command to copy video

libx264 = H.264 encoding library to use

-preset slow = a preset is a collection of options that provides a certain encoding speed to compression ratio

-crf 17 = Constant Rate Factor. CRF stipulates the rate control mode to keep the best quality vs. file size. This is the recommended rate control mode for most uses. This method allows the encoder to attempt to achieve a certain output quality for the whole file when output file size is of less importance. This provides maximum compression efficiency with a single pass. By adjusting the so-called quantizer for each frame, it gets the bitrate it needs to keep the requested quality level. The downside is that you can’t tell it to get a specific file size or not go over a specific size or bitrate, which means that this method is not recommended for encoding videos for streaming.

The range of the CRF scale is 0–51, where 0 is lossless, 23 is the default, and 51 is worst quality possible. A lower value generally leads to higher quality. 17 or 18 is close to visually lossless and should look the same or nearly the same as the input but isn’t technically lossless. The range is exponential, so increasing the CRF value +6 results in roughly half the bitrate / file size, while -6 leads to roughly twice the bitrate. Choose the highest CRF value that still provides an acceptable quality. If the output looks good, then try a higher value. If it looks bad, choose a lower value.

-tune film = allows you to change settings based upon the specifics of your input. For example, if your input is animation then use the animation tuning, or if you want to preserve grain in a film then use the grain tuning. If you are unsure of what to use or your input does not match any of the available tuning options then omit the -tune option. You can see a list of available tuning options with -tune help, and what settings they apply with x264 --fullhelp.

-c:a copy = copy audio as is, no changes

converted-movie.mkv = this is the new name of the converted video file

2. Iterating through a folder of video files and converting them as in #1

To iterate through a folder full of video files and convert them all simply wrap the above command in a DOS FOR loop

for %a in (*.mkv) do ffmpeg -i "%a" -c:v libx264 -preset slow -crf 17 -tune film -c:a copy "converted-%a"

Ok, couple of new things going on here:

for = begin for loop

%a = DOS parameter placeholder for each file in the folder

in (*.mkv) = this delineates the “set” of objects for the for loop to iterate over. It says for all MKV files in the current folder apply (do) the ffmpeg command.

"converted-%a" = again, same as above, instead of having to stipulate the output name of each file, it simply takes the name of each file and prepends “converted-” to the front of it and saves it in the same folder. When you wrap a parameter in quotes, it will account for delimiters such as spaces in a file name.

3. Using FFMpeg to show the video and audio codec information of a file

For video: ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 FILE_NAME.HERE

For audio: ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 FILE_NAME.HERE

These are virtually the same, the only difference is stipulating that you want to select the 1st (0th) element of the video or audio codec (v:0 or a:0). Breaking these down:

ffprobe = this is a ffmpeg utility to analyze a media file

-v error = this suppresses display of the ffprobe version information. Not necessary to get the codec information that we want, but makes a much cleaner output that’s easier to read.

-select_streams v:0 or a:0 = this flag tells ffprobe which video or audio stream you want to view the codec information for. If your file has more than one, you will need to change the 0 to a 1, 2, etc. The default that you’re usually interested in though is the first (or 0th) stream.

-show_entries = flag to print the codec information to the screen

stream=codec_name = instruction to ffprobe to tell it that we want to know what the name of the codec is

-of = flag to specify the default output format

default=noprint_wrappers=1:nokey=1 = these are key value pairs of “writers” that ffprobe will use to output information to the screen. noprint_wrappers stipulates to print or not print the section header. A value of 0 stipulates to print, a a stipulates to not print. The nokey stipulates to print or not print the key value of each field. Again, A value of 0 stipulates to print, a a stipulates to not print. In this case, we’re suppressing printing of anything beyond the codec name. I encourage you to play around with these values to see what other information is available.

FILE_NAME.HERE = This is a placeholder for the file that you want ffprobe to provide information about.

4. Iterating through a folder of files to show the video or audio codec information of all the files

For video: for %a in (*.*) do ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 “%a”

For audio: for %a in (*.*) do ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 “%a”

This is the same as #2 above where we use a FOR block to iterate through all the files in a folder to display the codec information for each file. If there are a mix of file types (e.g. video & audio together), than these may fail on a file that does not have a video or audio stream.

I hope this helps you – I know for myself that figuring out the for loops to work with spaces in file names, etc. was a real challenge getting the syntax correctly. If you find a better way or an error in any of my work please tell me in the comments below!

Helpful resources that I used in compiling this post:

  1. https://trac.ffmpeg.org/wiki/Encode/H.264
  2. https://catswhocode.com/ffmpeg-commands/
  3. https://ffmpeg.org/ffprobe.html