Encoding with the ffmpeg command line tool

ffmpeg howto

Encoding with the ffmpeg command line tool

GENERAL SYNTAX
ffmpeg <global-options> <input-options> -i <input> <output-options> <output>
Global options for log output, file overwriting, …
Input options for reading files
Output options for:
conversion (codec, quality, …)
filtering
stream mapping

Full help: ffmpeg -h full or man ffmpeg – but it’s huge!
##################################################################################################
TRANSCODING AND TRANSMUXING
Transcoding from one codec to another (e.g. H.264 using libx264):

ffmpeg -i <input> -c:v libx264 output.mp4
Transmuxing from one container/format to another – without re-encoding:

ffmpeg -i input.mp4 -c copy output.mkv
ffmpeg will take one video, audio, and subtitle stream from the input and map it to the output.

Explanation:

-c sets the encoder (see ffmpeg -encoders)
-c copy only copies bitstream
-c:v sets only video encoders
-c:a sets only audio encoders
-an and -vn would disable audio or video streams
##################################################################################################
TRANSCODING BACKGROUND
From http://ffmpeg.org/ffmpeg-all.html:

ffmpeg […] read[s] input files and get packets containing encoded data from them. When there are multiple input files, ffmpeg tries to keep them synchronized […]. Encoded packets are then passed to the decoder. […] The decoder produces uncompressed frames […] which can be processed further by filtering […]. After filtering, the frames are passed to the encoder, which encodes them and outputs encoded packets. Finally those are passed to the muxer, which writes the encoded packets to the output file.
##################################################################################################
SEEKING AND CUTTING
Cut a video from timestamp <start> for <duration>, or until <end>:

ffmpeg -ss <start> -i <input> -t <duration> -c copy <output>
ffmpeg -ss <start> -i <input> -to <end> -c copy <output>
Examples:

ffmpeg -ss 00:01:50 -i <input> -t 10.5 -c copy <output>
ffmpeg -ss 2.5 -i <input> -to 10 -c copy <output>
##################################################################################################
NOTES ABOUT SEEKING
When re-encoding video, seeking is always accurate to the timestamp
When copying bitstreams (-c copy), ffmpeg may copy frames that are not shown but necessary to include
Cutting with -c copy may yield video that starts with black frames (on unsupported players)
Also see:
http://trac.ffmpeg.org/wiki/Seeking
https://superuser.com/questions/138331/using-ffmpeg-to-cut-up-video
##################################################################################################
SETTING QUALITY
The output quality depends on encoder defaults and the source material
Do not just encode without setting any quality level!
Generally: You need to choose a target bitrate or quality level
Target bitrate depends on the video genre, size and framerate
##################################################################################################
OPTIONS FOR SETTING QUALITY
Possible options (just examples):

-b:v or -b:a to set bitrate
e.g., -b:v 1000K = 1000 kbit/s, -b:v 8M = 8 Mbit/s
-q:v or -q:a to set fixed-quality parameter
e.g., -q:a 2 for native AAC encoder
Examples of encoder-specific options:

-crf to set Constant Rate Factor for libx264/libx265
-vbr to set constant quality for FDK-AAC encoder
Many many more; see e.g. ffmpeg -h encoder=libx264 for examples
WHAT IS CRF?
CRF = Constant Rate Factor
Maintain constant quality across the entire encode
Good for storing video at fixed quality if file size is not important
EXAMPLE: TRANSCODING TO H.264, PT. 1
Constant quality (CRF) encoding:

ffmpeg -i <input> -c:v libx264 -crf 23 -c:a aac -b:a 128k output.mkv
For H.264, CRF between 18 and 28 looks “good”, lower is better. (Different CRF for HEVC and VP9.)

EXAMPLE: TRANSCODING TO H.264, PT. 2
Two-pass encoding:

ffmpeg -y -i <input> -c:v libx264 -b:v 8M -pass 1 -c:a aac -b:a 128k -f mp4 /dev/null
ffmpeg -i <input> -c:v libx264 -b:v 8M -pass 2 -c:a aac -b:a 128k output.mp4
(Windows: Use NUL instead of /dev/null)

See https://trac.ffmpeg.org/wiki/Encode/H.264
##################################################################################################
WHAT IS CRF?
CRF = Constant Rate Factor
Maintain constant quality across the entire encode
Good for storing video at fixed quality if file size is not important
##################################################################################################
EXAMPLE: TRANSCODING TO H.264, PT. 1
Constant quality (CRF) encoding:

ffmpeg -i <input> -c:v libx264 -crf 23 -c:a aac -b:a 128k output.mkv
For H.264, CRF between 18 and 28 looks “good”, lower is better. (Different CRF for HEVC and VP9.)

EXAMPLE: TRANSCODING TO H.264, PT. 2
Two-pass encoding:

ffmpeg -y -i <input> -c:v libx264 -b:v 8M -pass 1 -c:a aac -b:a 128k -f mp4 /dev/null
ffmpeg -i <input> -c:v libx264 -b:v 8M -pass 2 -c:a aac -b:a 128k output.mp4
(Windows: Use NUL instead of /dev/null)

See https://trac.ffmpeg.org/wiki/Encode/H.264
##################################################################################################
RATE CONTROL
Different kinds of rate control:

Constant Bitrate (CBR)
Variable Bitrate (VBR)
Average bitrate (ABR)
Constant quantization parameter (CQP)
Constant quality, based on psychovisual properties, e.g. CRF in x264/x265/libvpx-vp9
Constrained bitrate (VBV)
Which rate control to use for which case? More info: https://slhck.info/video/2017/03/01/rate-control.html

Important: Rate depends on content characteristics!
##################################################################################################
SPEED/QUALITY PRESETS IN X264
Choose the encoding speed for libx264 with the preset option:

ffmpeg -i <input> -c:v libx264 -crf 23 -preset ultrafast -an output.mkv
ffmpeg -i <input> -c:v libx264 -crf 23 -preset medium -an output.mkv
ffmpeg -i <input> -c:v libx264 -crf 23 -preset veryslow -an output.mkv
All presets: ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow

Example results (all have the same quality!):

Preset Encoding Time File Size
ultrafast 4.85s 15M
medium 24.13s 5.2M
veryslow 112.23s 4.9M
##################################################################################################
CHANGING FRAMERATE
Simple way to change the framerate by dropping or duplicating frames:

ffmpeg -i <input> -r 24 <output>
More complex ways involve filtering, see fps, mpdecimate, minterpolate filters:

ffmpeg -i <input> -filter:v fps=24 <output>
##################################################################################################
STREAM MAPPING
Each file and its streams have a unique ID, starting with 0.

Examples:

0:0 is the first stream of the first input file
0:1 is the second stream of the first input file
2:a:0 is the first audio stream of the third input file

You can map input streams to output, e.g. to add audio to a video:

ffmpeg -i input.mp4 -i input.m4a -c copy -map 0:v:0 -map 1:a:0 output.mp4
See: http://trac.ffmpeg.org/wiki/Map
##################################################################################################
SIMPLE FILTERING
ffmpeg has lots of video, audio, subtitle filters:

ffmpeg -i <input> -filter:v “<filter1>,<filter2>,<filter3>” <output>
A <filter> has a name and several options, and some pre-defined variables:

-filter:v <name>=<option1>=<value1>:<option2>=<value2>
##################################################################################################
SCALING
Scale to 320×240:

ffmpeg -i <input> -vf “scale=w=320:h=240” <output>
Scale to a height of 240 and keep aspect ratio divisible by 2:

ffmpeg -i <input> -vf scale=w=-2:h=240 <output>
Scale to 1280×720 or smaller if needed:

ffmpeg -i <input> -vf “scale=1280:720:force_original_aspect_ratio=decrease” <output>
More tips:

http://trac.ffmpeg.org/wiki/Scaling%20(resizing)%20with%20ffmpeg
https://superuser.com/questions/547296/
##################################################################################################
PADDING
Add black borders to a file, e.g. 1920×800 input to 1920×1080:

ffmpeg -i <input> -vf “pad=1920:1080:(ow-iw)/2:(oh-ih)/2” <output>

Note that:

You can use mathematical expressions
ow and oh are output width and height
iw and ih are input width and height
##################################################################################################
FADING
Simple fade-in and fade-out at a specific time for a specific duration.

ffmpeg -i <input> -filter:v \
“fade=t=in:st=0:d=5,fade=t=out:st=30:d=5” \
<output>
##################################################################################################
DRAWING TEXT
Complex system for printing text on video:

ffmpeg -i <input> -vf \
drawtext=”text=’Test Text’:x=100:y=50:\
fontsize=24:fontcolor=yellow:box=1:boxcolor=red” \
<output>
Various options related to font family, size, position, color, …
Text expansion (burn in frame number or timecode)
See: http://ffmpeg.org/ffmpeg-all.html#drawtext-1
##################################################################################################
COMPLEX FILTERING
Complex filters have more than one in- and/or output:

ffmpeg -i <input1> -i <input2> -filter_complex \
“[0:v:0][1:v:0]overlay[outv]” \
-map “[outv]” <output>
Steps:

Specify inputs to filterchain (e.g. [0:v:0][1:v:0])
Specify filters in the chain (e.g. overlay)
Specify output labels of chain (e.g. [outv])
Map output labels to final output file
You can have multiple filterchains with ;
See: http://ffmpeg.org/ffmpeg-all.html#Filtergraph-syntax-1
##################################################################################################
CONCATENATING STREAMS
Decode three video/audio streams and append to one another:

 

ffmpeg -i <input1> -i <input2> -i <input3> -filter_complex \
“[0:0][0:1][1:0][1:1][2:0][2:1]concat=n=3:v=1:a=1[outv][outa]” \
-map “[outv]” -map “[outa]” <output>
See: http://trac.ffmpeg.org/wiki/Concatenate (also for other methods)
##################################################################################################
TIMELINE EDITING
Enable filters only at a specific point in time.

Example:

Show a watermark in the top left corner
Between seconds 1 and 2 only
ffmpeg -i <video> -i <watermark> -filter_complex \
“[0:v][1:v]overlay=10:10:enable=’between(t,1,2)'[outv]” \
-map “[outv]” <output>
See: http://ffmpeg.org/ffmpeg-all.html#Timeline-editing
##################################################################################################
CALCULATING SIMPLE QUALITY METRICS
PSNR (Peak Signal To Noise Ratio):
$ ffmpeg -i <degraded> -i <reference> -filter_complex psnr -f null /dev/null
[Parsed_psnr_0 @ 0x7fdb187045c0] PSNR y:33.437789 u:39.814416 v:39.319141 average:34.698320 min:29.305186 max:inf
SSIM (Structural Similarity):
$ ffmpeg -i <degraded> -i <reference> -filter_complex ssim -f null /dev/null
[Parsed_ssim_0 @ 0x7fbf0500b660] SSIM Y:0.925477 (11.277116) U:0.948906 (12.916325) V:0.946795 (12.740513) All:0.932935 (11.735054)
##################################################################################################
MANY OTHER FILTERS
Examples:

Scene change detection using the select filter
Removing watermarks (delogo)
Blurring, edge detection and convolution filters
Video stabilization
Vectorscopes, histograms and other information
Chroma and alpha keying
Subtitle editing

Leave a Reply

Your email address will not be published. Required fields are marked *