MarcosBL
3/15/2014 - 2:23 PM

ffmpeg FLV to MP4 converter with progress bar

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