ffmpeg FLV to MP4 converter with progress bar
#!/bin/bash
####################################################################################
# ffmpeg flv2mp4 converter with progress indicator
# USAGE
# ./flv2mp4 VideoId
# Modify to your own needs
###################################################################################
SCRIPT=flv2mp4
LOG=/var/log/flv2mp4.log
show_prog_bar() {
local c="$1" # Character to use to draw progress bar
local v=$2 # Percentage 0<= value <=100
local t=$3 # Text before
local pbl=50 # Progress bar length in characters
local r=`expr 100 / $pbl` # Ratio between percentage value and progress bar length
local p="$v%" # Percentage value to display in the middle of progress bar
local l=${#p} # Length of string to display
local pbs="" # Progress bar string
local k=`expr \( $pbl - $l \) / 2` # Position where to substitute in progress bar string
local n1=`expr $v / $r`
local n2=`expr $pbl - $n1`
for (( i=0; i<$pbl; i++ )); do
pbs="${pbs}${c}"
done
pbs=`echo "$pbs" | sed 's/^\(.\{'"${k}"'\}\)\(.\{'"${l}"'\}\)\(.*$\)/\1'"${p}"'\3/'`
printf "\r\e[0m${t} \e[1;42m%s\e[1;41m%s\e[0m%s" "${pbs:0:$n1}" "${pbs:$n1:$n2}" "${c}"
}
display () {
START=$(date +%s); FR_CNT=0; ETA=0; ELAPSED=0
while [ -e /proc/$PID ]; do # Is FFmpeg running?
sleep 1
VSTATS=$(awk '{gsub(/frame=/, "")}/./{line=$1-1} END{print line}' \
/tmp/vstats) # Parse vstats file.
if [ $VSTATS -gt $FR_CNT ]; then # Parsed sane or no?
FR_CNT=$VSTATS
PERCENTAGE=$(( 100 * FR_CNT / TOT_FR )) # Progbar calc.
ELAPSED=$(( $(date +%s) - START )); echo $ELAPSED > /tmp/elapsed.value
ETA=$(date -d @$(awk 'BEGIN{print int(('$ELAPSED' / '$FR_CNT') * ('$TOT_FR' - '$FR_CNT'))}') -u +%H:%M:%S) # ETA calc.
fi
show_prog_bar " " $PERCENTAGE "\tFrame: $FR_CNT / $TOT_FR - Consumido: $(date -d @$ELAPSED -u +%H:%M:%S) Restante: $ETA"
done
}
trap "echo -e \"\tConversión interrumpida\"; echo ; killall ffmpeg $SCRIPT; rm -f "$RM/vstats*"; exit" INT TERM # EXIT Kill & clean if stopped.
# Delete destination file
if [[ ! -f $1.flv ]] ; then
echo "El fichero $1.flv no existe, abortando..."
exit
fi
rm -fr $1.mp4
# Get duration and PAL/NTSC fps then calculate total frames.
FPS=$(ffprobe "$1.flv" 2>&1 | sed -n "s/.*, \(.*\) tbr.*/\1/p")
DUR=$(ffprobe "$1.flv" 2>&1 | sed -n "s/.* Duration: \([^,]*\), .*/\1/p")
HRS=$(echo $DUR | cut -d":" -f1)
MIN=$(echo $DUR | cut -d":" -f2)
SEC=$(echo $DUR | cut -d":" -f3)
TOT_FR=$(echo "($HRS*3600+$MIN*60+$SEC)*$FPS" | bc | cut -d"." -f1)
if [ ! "$TOT_FR" -gt "0" ]; then echo error; exit; fi
# Re-code with it.
ffmpeg -vstats_file /tmp/vstats -i "$1.flv" -f mp4 -vcodec libx264 -r 25 -b 560000 -ab 64 -ar 44100 -threads 0 "$1.mp4" 2>/dev/null &
PID=$! &&
echo -e "\n\tPID de ffmpeg = $PID - Duración: $DUR - Frames: $TOT_FR"
display # Show progress.
rm -f "$RM"/vstats* # Clean up tmp files.
chown www-data.www-data $1.mp4
MP4SIZE=$(stat -c%s "$1.mp4")
# Update database (Optional)
#mysql --user="xxxxxxxxx" --password="xxxxxxxxx" --database="multimedia" --execute="UPDATE multimedia SET peso=$MP4SIZE, extension='mp4' WHERE id=$1"
printf "\n\n\tProceso finalizado\n\n"
# Show MP4 in folder
ls -la $1.mp4 | while read x; do echo -e "\t$x"; done
echo -e "\n\n"
# Remove original (Optional)
# rm -fr "$1.flv"
ls -la $1* | while read x; do echo -e "\t$x"; done
# Statistics for logfile entry.
((BATCH+=$(cat /tmp/elapsed.value))) # Batch time totaling.
ELAPSED=$(cat /tmp/elapsed.value) # Per file time.
echo -e "\Duracion: $DUR - Frames: $TOT_FR \n" >> $LOG
AV_RATE=$(( TOT_FR / ELAPSED ))
echo -e "Tiempo consumido: $(date -d @$ELAPSED -u +%H:%M:%S) a una media de $AV_RATE""fps.\n" >> $LOG
exit