Skip to content

Instantly share code, notes, and snippets.

@codyopel
Created August 25, 2014 00:04
Show Gist options
  • Save codyopel/cbeec85da523171662e4 to your computer and use it in GitHub Desktop.
Save codyopel/cbeec85da523171662e4 to your computer and use it in GitHub Desktop.
FFmpeg with progress bar (re-work)
#!/bin/bash
# File name: ZAVI2MPG - saved in the "nautilus-scripts" directory.
# Author: robz
# Version: 130511
# This is a re-re-work of a previous script for converting .avi television
# files to a "burnable to DVD" format. This time though conversion statistics
# visual output is supplied by the Zenity dialogue. Stats logfile also added.
# File locations in some variables are specific to my PC check "# Vars" first.
# The script is called by right clicking on the ".avi file" then clicking
# the appropriate choice in the nautilus-scripts menu.
# You'll need "FFmpeg" an FFmpeg notify-send icon and a ding-dong.wav sound.
# Vars.
ICON=$HOME/Pictures/user_graphics/Icons/ffmpeg-logo-small.png
LOG=$HOME/Torrents/re-coding.log
display () # Calculate/collect progress bar info. & pipe to Zenity.
{
START=$(date +%s); FR_CNT=0; ETA=0; ELAPSED=0
while [ -e /proc/$PID ]; do # Is FFmpeg running?
sleep 2
VSTATS=$(awk '{gsub(/frame=/, "")}/./{line=$1-1} END{print line}' \
"$RM"/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
echo "# Working on file: $COUNT of $OF - Length: $DUR - Frames: $TOT_FR\
\nFilename: ${NFILE%.*}\nSaved to: $SAVEAS\
\nTelevision standard is set to: $TFORM2\
\nRe-coding with FFmpeg, method: $QUAL\
\nFrame: $FR_CNT of $TOT_FR Elapsed: $(date -d @$ELAPSED -u\
+%H:%M:%S) ET to finish: $ETA" # Text for stats. output.
echo $PERCENTAGE # Feed the progbar.
done | zenity\
--progress\
--window-icon $ICON\
--title="AVI-2-MPG ${QUAL:10:13}"\
--text="Initializing please wait..."\
--percentage=0\
--auto-close\
--auto-kill
}
SEL=$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS # Right clicked selection.
RM=$(pwd)
trap "killall ffmpeg ZAVI2MPG; rm -f "$RM/ffmpeg2pass*" "$RM/vstats*"; exit" \
INT TERM EXIT # Kill & clean if stopped.
# Select re-coded file destination.
SAVEAS=$(zenity --file-selection --directory\
--window-icon $ICON --title ">>SELECT DESTINATION FOR RE-CODED FILE<<")
if [ "$?" = 1 ]; then
exit $?
fi
# Select quality of re-code.
QUAL=$(zenity --window-icon $ICON --title "AVI-2-MPG"\
--width 340 --height 170 --list --text "Recode Mode"\
--radiolist --column "Select " --column "FFmpeg re-code option"\
FALSE 'One Pass, same Q big file, fast.'\
TRUE 'Two Pass, same Q smaller file, slow.');
if [ $? = 1 ]; then
exit $?
elif [ "${QUAL:0:8}" = "One Pass" ]; then
QUAL="One Pass - Re-coding..."
fi
SAVEIFS=$IFS # Make "for loops" handle
IFS=$(echo -en "\n\b") # filenames with spaces.
for FILE in $SEL; do ((OF+=1)); done # Count right click
echo -e $(date +%c)" - Files processed: $OF\n" >> $LOG # selected files, log.
# Loop through counted file selection and process in turn.
for FILE in $SEL; do ((COUNT+=1))
NFILE=$(basename "$FILE")
# Get duration and PAL/NTSC fps then calculate total frames.
FPS=$(ffprobe "$FILE" 2>&1 | sed -n "s/.*, \(.*\) tbr.*/\1/p")
DUR=$(ffprobe "$FILE" 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 zenity --error; exit; fi
# TV format to FFmpeg friendly.
TFORM=$(echo "$FPS" |\
sed "s/25/pal-dvd/g; s/30/pal-dvd/g; s/29.98/ntsc-dvd/g;\
s/29.97/ntsc-dvd/g; s/23.98/ntsc-dvd/g;")
TFORM2=$(echo "$FPS" |\
sed "s/25/PAL @ 25fps/g; s/30/PAL @ 30fps/g;\
s/29.98/NTSC @ 29.98fps/g; s/29.97/NTSC @ 29.97fps/g;\
s/23.98/NTSC-Film @ 23.98fps/g;")
# Re-code with it.
if [ "$QUAL" = "One Pass - Re-coding..." ]; then # Same Q big file.
nice -n 15 ffmpeg -i "$FILE"\
-target $TFORM\
-sameq\
-r $FPS\
-vstats\
-y\
$SAVEAS/${NFILE%.*}.mpg & # Background FFmpeg.
PID=$! && display # GUI stats. func.
rm -f "$RM"/vstats* # Clean up tmp files.
else
QUAL="Two Pass - Analysing..." # Analyse video only.
nice -n 15 ffmpeg -i "$FILE"\
-pass 1\
-target $TFORM\
-r $FPS\
-vstats\
-b 2800k\
-an\
-y\
/dev/null & # Background FFmpeg.
PID=$! && display # GUI stats. func.
rm -f "$RM"/vstats* # Clean up.
AN_TM=$(cat /tmp/elapsed.value) # Get analyse time.
((BATCH+=$AN_TM)) # Batch time totaling.
QUAL="Two Pass - Re-coding..." # Do smaller re-code.
nice -n 15 ffmpeg -i "$FILE"\
-pass 2\
-target $TFORM\
-r $FPS\
-vstats\
-b 2800k\
-acodec ac3\
-ar 48000\
-ab 128k\
-y\
$SAVEAS/${NFILE%.*}.mpg & # Background FFmpeg.
PID=$! && display # GUI stats. func.
rm -f "$RM"/ffmpeg2pass* "$RM"/vstats* # Clean up tmp files.
fi
# Statistics for logfile entry.
((BATCH+=$(cat /tmp/elapsed.value))) # Batch time totaling.
ELAPSED=$(cat /tmp/elapsed.value) # Per file time.
echo -e $COUNT\. ${NFILE%.*}\
"\nDuration: $DUR - Total frames: $TOT_FR\
\nCoded to $TFORM2 standard using \"${QUAL:0:8}\" option." >> $LOG
# Elapsed time for 1 pass, average for 2 passes, fps average for both.
if [ "${QUAL:0:8}" = "Two Pass" ]; then
((ELAPSED+=$AN_TM)); AV_RATE=$(( TOT_FR * 2 / ELAPSED ))
else
AV_RATE=$(( TOT_FR / ELAPSED ))
fi
echo -e "Re-coding time taken: $(date -d @$ELAPSED -u +%H:%M:%S)"\
"at an average rate of $AV_RATE""fps.\n" >> $LOG
done
# Notify finished batch ding-dong gong and message, log it, all done bye ;¬)
TEXT="Total re-coding time: $(date -d @$BATCH -u +%H:%M:%S)."
echo -e "$TEXT\n\
__________________________________________________________________" >> $LOG
notify-send -i $ICON "ZAVI2MPG Re-code completed" "$TEXT"
/usr/bin/canberra-gtk-play --volume 2 -f $HOME/Audio/2tone.wav
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment