[BETA][BASH] Convertitore video per device Android!
Ciao ragazzi!
Ho creato questo (secondo, più avanzato) script per la conversione dei video (qualsiasi formato) in video compatibili con Android (H.264/AAC). Supporta varie risoluzioni. Attualmente (per un bug di FFmpeg) l'audio in DTS è sballato (diciamo pure girato di 90° a sinistra). Se il contenitore è matroska (.mkv) cercherà prima una traccia AC3 e solo se non la trova prenderà la prima traccia audio che trova (di solito, appunto, DTS). L'aspect ratio viene cercato in modo automatico, se non lo trova lo richiede (facendovi vedere la risoluzione del filmato originale).
Eseguibili richiesti: ffmpeg, mkvtoolnix (comprendente gli strumenti per il formato matroska come mkvmerge, mkvextract etc)
FFmpeg 0.5.1 per Ubuntu con librerie closed (necessario per encoding in AAC)
avc (chmod +x avc)
codice:
#!/bin/bash
echo -e "EleGoS' Advanced Video Converter for Android Devices v.1.8.3\n"
function echoHelp() {
echo "Options (required):"
echo -e "\ti: the video to convert"
echo "Usage:"
echo -e "\t$0 -i MyMovie.ext"
}
if [ $# -eq 0 ]; then
echoHelp
exit 0
fi
while getopts "i:o:h" Option
do
case $Option in
i ) input=${OPTARG};;
* )
echoHelp
exit 0
;;
esac
done
ffmpeg_check=$(which ffmpeg)
matroska_check=$(which mkvmerge)
if [[ -z $ffmpeg_check ]] || [[ -z $matroska_check ]]; then
echo -e "\nffmpeg or mkvtoolnix not installed! Please install them."
exit 0
fi
if [ ! -f $input ]; then
echo -e "\n $input not found."
exit 0
fi
output=$(basename $input)
output=${output%.*}
output=$output-android.mp4
# get some info from the original video
ffmpeg -i $input 2>ffmpeg.tmp
# presets and preferences
source preferences.avc
source functions
if [ -z $device_height ] || [ -z $device_width ]; then
echo -e "\nIt was impossible to find your device, please check the resolutions.preset file. Please insert your device screen resolution (in landscape):"
read -p "Height: " device_height
read -p "Width: " device_width
fi
# check if it's in a Matrioska format (audio extraction)
matroska=0
check=$(isMatroska $input)
if [ $check -eq 1 ]; then
matroska=1
fi
# get the aspect ratio
aspect_ratio=$(getAspectRatio ffmpeg.tmp)
if [[ $aspect_ratio = "" ]]; then
echo "The script was not able to detect the aspect ratio."
echo "Please input the right AR (see the next line to guess it)."
cat ffmpeg.tmp | grep "Video"
read aspect_ratio
fi
# get the original video size
video_original_size=$(cat ffmpeg.tmp | grep Video | awk 'BEGIN{RS=","}/x/{print $1}')
stream=$(echo $video_original_size | grep Stream)
if [[ ! -z $stream ]]; then
for word in $video_original_size
do
check=$(echo $word | grep x)
if [[ ! -z $check ]]; then
video_original_size=$word
break
fi
done
fi
IFS='x' read video_original_width video_original_height <<< "$video_original_size"
if [[ -z $video_original_height ]] || [[ -z $video_original_width ]]; then
echo "The script was not able to detect the video resolution."
echo "Please input the right values (see the next line to get them)."
cat ffmpeg.tmp | grep "Video"
read -p "Height: " video_original_height
read -p "Width: " video_original_width
fi
new_video_size=($(resizeVideo $video_original_height $video_original_width $device_height $device_width))
inner_height=${new_video_size[0]}
inner_width=${new_video_size[1]}
let height_dif=($device_height-$inner_height)
let width_dif=($device_width-$inner_width)
let pad_height=($height_dif/2)
let pad_width=($width_dif/2)
if [[ $height_dif -lt 0 ]]; then
let height_dif="($height_dif*(-1))"
fi
if [[ $width_dif -lt 0 ]]; then
let width_dif="($width_dif*(-1))"
fi
pad_height_rest=`expr $pad_height % 2`
pad_width_rest=`expr $pad_width % 2`
if [ $pad_height_rest -eq 0 ] || [ $pad_height -eq 0 ]; then
pad_top_bottom="-padtop $pad_height -padbottom $pad_height"
pad_top=$pad_height
else
let pad_top=($pad_height-1)
let pad_bottom=($pad_height+1)
pad_top_bottom="-padtop $pad_top -padbottom $pad_bottom"
fi
if [ $pad_width_rest -eq 0 ] || [ $pad_width -eq 0 ]; then
pad_left_right="-padleft $pad_width -padright $pad_width"
pad_left=$pad_width
else
let pad_left=($pad_width-1)
let pad_right=($pad_width+1)
pad_left_right="-padleft $pad_left -padright $pad_right"
fi
if [ "$vf_pad" -gt "0" ]; then
pad_left_right=""
pad_top_bottom="-vf pad=$device_width:$device_height:$pad_left:$pad_top"
fi
x="x"
device="$inner_width$x$inner_height"
#extract the audio track
if [ $matroska -eq 1 ]; then
track=$(mkvmerge -i $input | grep "AC3" | awk '/audio/ { sub(/:$/, "", $3); print $3; exit }')
if [ -z $track ]; then
track=$(mkvmerge -i $input | awk '/audio/ { sub(/:$/, "", $3); print $3; exit }')
fi
mkvextract tracks $input $track:audio.raw.tmp
ffmpeg -i audio.raw.tmp -vn -acodec libfaac -ab $audio_bitrate -ac 2 audio.aac
else
ffmpeg -i $input -vn -acodec libfaac -ab $audio_bitrate -ac 2 audio.aac
fi
ffmpeg -i $input -threads 0 -an -pass 1 -s $device $pad_top_bottom $pad_left_right -aspect $aspect_ratio -vcodec libx264 -b $video_bitrate -flags +loop -cmp +chroma -partitions 0 -me_method epzs -subq 1 -trellis 0 -refs 1 -coder 0 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bt $video_bitrate -maxrate 768k -bufsize 2M -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -level 13 -f rawvideo -y /dev/null
ffmpeg -i $input -threads 0 -an -pass 2 -s $device $pad_top_bottom $pad_left_right -aspect $aspect_ratio -vcodec libx264 -b $video_bitrate -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me_method umh -subq 5 -trellis 1 -refs 5 -coder 0 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bt $video_bitrate -maxrate 768k -bufsize 2M -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -level 13 tmp-video.mp4
ffmpeg -i tmp-video.mp4 -i audio.aac -threads 0 -acodec libfaac -ab $audio_bitrate -ac 2 -vcodec copy $output
rm *.tmp *.aac tmp-video.mp4 *.log*
exit 0
functions
codice:
# returns 1 if it's in the Matroska format
function isMatroska() {
file=$1
#extension check
ext=${file/*./}
if [[ $ext = "mkv" ]]; then
echo 1
exit 0
fi
#ffmpeg check
if [ -f "ffmpeg.tmp" ]; then
ffmpeg -i $file 2>ffmpeg.tmp
fi
log=$(cat ffmpeg.tmp | grep "matroska")
if [[ -n $log ]]; then
echo 1
exit 0
fi
echo 0
exit 0
}
# number1 number2
function max2() {
if [[ "$1" -gt "$2" ]]; then
echo $1
else
echo $2
fi
}
# original height, width, device height, width
function resizeVideo() {
echo "D/resizeVideo: init" >&2
h1=$1
w1=$2
h1orig=$1
w1orig=$2
h2=$3
w2=$4
max=$(max2 $h1 $w1)
if [ $max = "$h1" ]; then
h1=$h2
let w1="(($w1orig*$h1)/$h1orig)"
if [ $w2 -lt $w1 ]; then
h1orig=$h1
w1orig=$w1
w1=$w2
let h1="(($w1*$h1orig)/$w1orig)"
fi
else
w1=$w2
let h1="(($w1*$h1orig)/$w1orig)"
if [ $h2 -lt $h1 ]; then
h1orig=$h1
w1orig=$w1
h1=$h2
let w1="(($w1orig*$h1)/$h1orig)"
fi
fi
new_video_resize[0]=$h1
new_video_resize[1]=$w1
if [ $w2 -lt $w1 ] || [ $h2 -lt $h1 ]; then
new_video_resize=($(resizeVideo $h1 $w1 $h2 $w2))
fi
echo ${new_video_resize[0]} ${new_video_resize[1]}
}
# ffmpeg_output_file
function getAspectRatio() {
log=$(cat $1 | grep "PAR")
if [[ -n $log ]]; then
check=$(echo $log | grep "\[")
if [[ -z $check ]]; then
video_aspect=$(echo $log | awk 'BEGIN{RS=","}/PAR /{print $4}')
else
video_aspect=$(echo $log | awk 'BEGIN{RS=","}/PAR /{print substr($5, 0, length($5) -1)}')
fi
fi
echo $video_aspect
}
preferences.avc (edita la risoluzione)
codice:
audio_bitrate=128k
video_bitrate=500k
device_height=480
device_width=800
# used for newly SVN builds of FFmpeg ("please use vf=pad") (1=yes)
vf_pad=0
## Acer A1 Liquid, HTC Desire, Nexus One
# => 480x800
## HTC (Dream, Hero, Legend, Magic), Samsung (i5700, i7500)
# => 320x480
## HTC Tatoo
# => 240x320
## Motorola (Droid, Milestone), Sony Xperia X10
# => 480x854
Per favore riportate qualsiasi bug/commento!
Per ora l'ho testato su piccoli file in 16:9, vedete di provare con dei filmati 4:3, formati diversi etc. Teoricamente è anche possibile convertire i filmati di YouTube.