Well, i’m more or less new to video-encoding. I’m playing around with mencoder and other tools for some years, though i’m never gone into detail nor i tried to understand. This changed somehow in the past few weeks, thus i was reading everything again what i already read ago some years. This said you might know that there are a lot of information and websites about how to encode videos and video-editing in general. It’ll take you weeks to read all of them – Thus i wrote this little article, covering the information i’m interested in. It might or might not be helpful for you – For me it’s some sort of reminder :)
Questions & Answers
I got a lot of Questions and managed to ask a few guys (for example in the Freenode Channel #mplayer on irc.freenode.net) to answer those, some of the answers i found in the man-pages or documentation of several projects.
Reason(s) for Encoding, or: Why should i re-encode a Video.
The simpliest answer to this is: You should not. Encoding a Video, or Re-Encoding a Video is mostly done to make the overall filesize smaller, or to play it on another hardware or software player (or on lower-end hardware). As soon as you encode a Video to a compressed format, it will loose information. If you re-encode a already compressed video it will loose even more information. If you want the highest Quality, you don’t want to (re-)encode a video, you want to let it as it is.
Black Borders: Bad or Good?
The mencoder documentation says (25th dec 09) that you want to avoid black borders within a video, because they hurt quality. On another page in the documentation they give examples how to add black borders with the expand video filter. One might get confused, first they say it’s bad, and then they show you how to do it. The documentation is correct though: Some Video Players (Hard & Software) don’t play videos correctly if the dimensions aren’t correct. You can make the dimensions (resolution) correct by adding black borders. Thus the Answer to this question is: Try to Avoid them, use them only if needed.
Can you improve Quality of Videos by Re-Encoding?
Even if i’d answer “yes” this wouldn’t be true. And if you don’t know the answer, you probably didn’t read the first Entry in this small FAQ. No. Video Quality does not get better if you re-encode a video. There are a few Reasons why it might look better, it could probably look more softer (loosing detail, means losing noise). It might also be possible to remove artifacts by re-encoding.
Formula / Maths
Due to reading a lot of pages, i found out some useful formula to calculate some stuff and i added my own stuff. Here’s a list:
Calculating the Bitrate with a given target_size.
BITRATE = ( TARGET_SIZE_IN_MB - SOUND_SIZE_IN_MB ) * 1024 * 1024 / LENGTH_IN_SEC * 8 / 1000
Example:
# A Video of 90 Minutes (5400 Seconds) with 120 MB
# of Audio - We want a Size of 700 MB overall.
( 700 - 120 ) * 1024 * 1024 / 5400 * 8 / 1000
= 900.99863
Explaination:
In case you’re using a fixed bitrate for video-encoding (like i) this might be useful. You can calculate what bitrate you need for a given Filesize. You need to set a bitrate for example for Two-Pass Encoding.
Calculate the Bits per Pixel
BPP = ( BITRATE * 1000 ) / ( WIDTH * HEIGHT * FPS )
Example:
( 900 * 1000 ) / ( 784 * 326 * 25 )
= 0.14085
Explaination:
This Formula can give you an “idea” on how good your movie will look later with your settings (Resolution and Bitrate). Of course it depends on the Source Material and a few other things, however, it can give you an idea whether to change the bitrate or the resolution. Here’s a list what the resulting lines could mean:
0.0 - 0.15 = Will most likely look bad
0.16 - 0.20 = Will look okay, you might notice blocks
0.21 - 0.25 = Will look good
> 0.25 = You won't notice much difference or you're wasting bits.
Calculate the Bits per Block
BPB = ( BITRATE * 1000 ) / ( FPS * ( ( WIDTH * HEIGHT ) / BLOCKSIZE ) )
Example:
( 900 * 1000 ) / ( 25 * ( ( 784 * 326 ) / ( 16 * 16 ) )
= 36.05859
Explaination:
A Block is usually 16*16. The BPB are just another variant of the BPP (Which gives you numers with 0., while the BPB can have numbers starting with 0 up to 100 or more. The following List might give you an idea what BPB are good and which not:
0 - 39 = Most likely bad quality (might be still okay for you) 40 - 49 = Quality is okay 50 - 59 = Quality is good > 60 = You're wasting bits
Calculate nearest 16
NUM = VALUE + (( X - 0.( VALUE / 16 ) ) * 16 )
Example:
# VALUE = 700
700 + ( ( 1 - 0.75 ) * 16 )
= 704
# VALUE = 231
231 + ( ( 0 - 0.43750 ) * 16 )
= 224
Explaination:
One important side note: You might need to calculate with more than 2 numbers after the comma. 5 is a good choice. This depends ofc on how good your calculator is doing rounding. However. This Calculation is somewhat tricky. First you’re dividing the value through 16. Remove the part before the comma: 43,7544 = 0,7544. If that number is greater than 0.5, X will be 1, if it’s smaller than 0.5 X will be 0. (Thats was the tricky part). Now you just need to calculate as shown in my examples and it will give you the nearest through 16 dividable number. This is handy if you want to scale the width and height and want to make sure that it’s dividable through 16 (thats usually what you want at videos).
Getting Information & Calculating Stuff – Bash Snippets
Most people will tell you, and the documentation states “identify the source material”. Here are some Bash Snippets which will try to help you with that job. However, you still want to have some additional tools installed.
Calculate Bitrate
###
# this function
# calculates the bitrate. You need to provide:
# fps, length, audio-size in mb, wanted video size
#
# param fps
# param length
# param audio size
# param overall wanted size
# return $BITRATE
###
function calculateBitrate() {
local FPS=$1
local LENGTH=$2
local AUDIO_SIZE=$3
local SIZE=$4
# calculate with scale=5 to be more precise
local A=$(echo "scale=5;$SIZE - $AUDIO_SIZE" | bc);
local B=$(echo "scale=5;$A*1024*1024/$LENGTH*8/1000" | bc);
# remove the decimal part
local C=$(echo $B | sed 's/\..*//g');
NEWBITRATE=$C
}
Calculate the Size
function calculateSize() {
#calculateSize $FPS $LENGTH $AUDIO_SIZE $NEWBITRATE
local FPS=$1
local LENGTH=$2
local AUDIO_SIZE=$3
local BITRATE=$4
# calculate with scale=5 to be more precise
local A=$(echo "scale=5;$BITRATE*1000*$LENGTH/8/1024/1024" | bc);
local B=$(echo "scale=5;$A+$AUDIO_SIZE" | bc);
# remove the decimal part
local C=$(echo $B | sed 's/\..*//g');
NEWSIZE=$C
}
Calculate the BPB
###
# The Bits per Block (BPB) are also important
# 40-60 is a good value, everything below is not
# good for quality, and everything higher than 60
# is a waste of bits.
# You need to provide width, height, bitrate and
# fps to this function and it will tell you the
# bpb
#
# param width
# param height
# param bitrate
# param fps
# return $BPB
###
function calculateBPB() {
local WIDTH="$1"
local HEIGHT="$2"
local BITRATE="$3"
local FPS="$4"
local A=$(echo "$BITRATE * 1000" | bc);
local B=$(echo "$WIDTH * $HEIGHT" | bc);
local C=$(echo "$B / 256" | bc);
local D=$(echo "$FPS * $C" | bc);
local E=$(echo "$A / $D" | bc);
NEWBPB=$E;
}
Calculate Nearest 16
function calculateNearestSixteen() {
local VALUE="$1"
local A=$(echo "scale=2;$VALUE / 16" | bc);
local B=$(echo "$A" | sed 's/.*\.//g');
local C=0.$B;
if [[ $B -gt 50 ]]; then
local M=1;
else
local M=0;
fi
local D=$(echo "$M - $C" | bc);
local E=$(echo "$D * 16" | bc);
local F=$(echo "$VALUE + $E" | bc | sed 's/\..*//g');
NEWVALUE=$F;
}
Getting Length of a Video in Seconds
# getting the original duration
OV_DURATION=$(tcprobe -i "$INPUTFILE" -X | grep "duration" | awk 'NR == 1 { print $2; }');
# getting the hours
OV_HR=$(echo "$OV_DURATION" | cut -d ":" -f1 | sed 's/\..*//g');
OV_HRS=$(echo "$OV_HR*60*60" | bc);
# getting the minutes
OV_MI=$(echo "$OV_DURATION" | cut -d ":" -f2 | sed 's/\..*//g');
OV_MIS=$(echo "$OV_MI*60" | bc);
# getting the seconds
OV_SE=$(echo "$OV_DURATION" | cut -d ":" -f3 | sed 's/\..*//g');
# getting the length
OV_LENGTH=$(echo "$OV_HRS+$OV_MIS+$OV_SE" | bc);
Getting the FPS of a Video
# getting the framerate
OV_FPS=$(tcprobe -i "$INPUTFILE" -X | grep "frame rate" | awk 'NR == 1 { print $3; }');
Getting the Bitrate of a Video
# getting the bitrate
OV_BITRATE=$(tcprobe -i "$INPUTFILE" -X -M | grep "bitrate" | awk 'NR == 1 { print $2; }');
Getting Audio Data
# getting bitrate
OA_BITRATE=$(tcprobe -i "$INPUTFILE" -X -M | grep "bitrate" | awk 'NR == 2 { print $2; }');
# getting sample rate
OA_SAMPLERATE=$(tcprobe -i "$INPUTFILE" -X -M | grep "sample rate" | awk 'NR == 1 { print $3; }');
# getting bits per sample
OA_SAMPLEBITS=$(tcprobe -i "$INPUTFILE" -X -M | grep "bits for sample" | awk 'NR == 1 { print $3; }');
