Created
December 29, 2014 11:03
-
-
Save cocoabox/72e7ad26ff55887e13c8 to your computer and use it in GitHub Desktop.
remux .mkv into .mp4 (transcode audio to AAC) using ffmpeg, with progress indicator and time remaining
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
PURPLE=$(tput setaf 13) | |
RED=$(tput setaf 1) | |
CYAN=$(tput setaf 14) | |
YELLOW=$(tput setaf 11) | |
GREEN=$(tput setaf 2) | |
NONE=$(tput sgr0) | |
ERASE="`tput cuu1``tput el`" | |
if [ -z "$1" ]; then | |
echo "Usage: $(basename $0) [source movie file]" | |
exit 1 | |
fi | |
if [ ! -f "$1" ]; then | |
echo "${RED}ERROR: $1 : not found$NONE" | |
exit 1 | |
fi | |
FFMPEG=$(which ffmpeg 2>/dev/null) | |
if [ -z "$FFMPEG" ]; | |
# for my thecus N5550 | |
FFMPEG="/raid0/data/module/ffmpeg/sys/bin/ffmpeg" | |
if [ ! -f "$FFMPEG" ]; then | |
echo "$(RED) ffmpeg not found" | |
exit 666; | |
fi | |
fi | |
AUD=$("$FFMPEG" -i "$1" 2>&1 | sed -ne 's/^[ ]*Stream #0:\([0-9]*\).*: Audio: \([^\, ]*\), \(.*\)$/track="\1"; codec="\2"; etc="\3"/p') | |
VID=$("$FFMPEG" -i "$1" 2>&1 | sed -ne 's/^[ ]*Stream #0:\([0-9]*\).*: Video: \([^ (]*\)\(.*\)$/track="\1"; codec="\2"; etc="\3"/p') | |
TRANSCODE_AUDIO=0 | |
if [ "$2" == "force_aac" ]; then | |
TRANSCODE_AUDIO=1 | |
fi | |
if [ $(echo "$VID" | wc -l) -gt 1 ]; then | |
while read -r line; do | |
eval "$line" | |
echo "video ${PURPLE}$track ${YELLOW}$codec ${NONE}$etc"ERASE | |
done <<< "$AUD" | |
echo -n "--- Which ${PURPLE}video track${NONE} to use ? "; read VID_TRACK | |
VID_CODEC="" | |
while read -r line; do | |
eval "$line" | |
if [ "$track" == "$VID_TRACK" ]; then VID_CODEC="$codec"; break; fi | |
done <<< "$VID" | |
else | |
eval "$VID" | |
VID_TRACK="$track" | |
VID_CODEC="$codec" | |
fi | |
if [ -z "$VID_TRACK" -o -z "$VID_CODEC" ] ; then | |
echo "ERROR : video track or codec not specfied, or wasn't parsed properly in ffmpeg output" | |
exit 1 | |
fi | |
if [ "$VID_CODEC" != "h264" ]; then | |
echo "WARNING : non H.264 video stream; might not be playable on PS3" | |
fi | |
echo "--> will use video track ${CYAN}$VID_TRACK${NONE} encoded in ${CYAN}$VID_CODEC${NONE}" | |
if [ $(echo "$AUD" | wc -l) -gt 1 ]; then | |
while read -r line; do | |
eval "$line" | |
echo "audio ${PURPLE}$track ${YELLOW}$codec ${NONE}$etc" | |
done <<< "$AUD" | |
echo -n "--- Which ${PURPLE}audio track${NONE} to use ? "; read AUD_TRACK | |
AUD_CODEC="" | |
while read -r line; do | |
eval "$line" | |
if [ "$track" == "$AUD_TRACK" ]; then AUD_CODEC="$codec"; break; fi | |
done <<< "$AUD" | |
else | |
eval "$AUD" | |
AUD_TRACK="$track" | |
AUD_CODEC="$codec" | |
fi | |
PARAM_ACODEC="-c:a copy" | |
PARAM_AQUALITY="" | |
if [ -z "$AUD_TRACK" -o -z "$AUD_CODEC" ] ; then | |
echo "ERROR : audio track or codec not specfied, or wasn't parsed properly in ffmpeg output" | |
exit 1 | |
fi | |
if [ "$AUD_CODEC" == "aac" -a $TRANSCODE_AUDIO -eq 0 ]; then | |
echo "--> will copy audio track ${CYAN}$AUD_TRACK${NONE}" | |
else | |
echo "--> will transcode audio track ${CYAN}$AUD_TRACK${NONE} using libfaac" | |
PARAM_ACODEC="-c:a libfaac" | |
PARAM_AQUALITY="-q:a 100" | |
fi | |
OUT="$1.output.mp4" | |
if [ -f "$OUT" ]; then | |
echo -n "--> ${YELLOW}$OUT${NONE} already exists. Enter another name (Enter=delete existing) ? " | |
read FN | |
[[ -z "$FN" ]] && FN="$OUT" | |
[[ -f "$FN" ]] && rm -f "$FN" | |
OUT="$FN" | |
else | |
echo "--> output file is : ${CYAN}$OUT${NONE}" | |
fi | |
DURA=$("$FFMPEG" -i "$1" 2>&1 | sed -ne 's/^.*Duration: \([0-9]*\):\([0-9]*\):\([0-9]*\)\.\([0-9]*\).*$/hr=\1; min=\2; sec=3; msec=4/gp') | |
if [ -z "$DURA" ] ; then | |
"$FFMPEG" -i "$1" -c:v copy \ | |
$PARAM_ACODEC $PARAM_AQUALITY \ | |
-map 0:$VID_TRACK -map 0:$AUD_TRACK \ | |
"$OUT" | |
exit 1 | |
else | |
eval "$DURA" | |
hr=$(expr $hr + 0); min=$(expr $min + 0); sec=$(expr $sec + 0); msec=$(expr $msec + 0) | |
((TOTAL_SEC = hr * 3600 + min * 60 + sec)) | |
echo "TOTAL $TOTAL_SEC sec" | |
"$FFMPEG" -i "$1" -c:v copy \ | |
$PARAM_ACODEC $PARAM_AQUALITY \ | |
-map 0:$VID_TRACK -map 0:$AUD_TRACK \ | |
-loglevel debug \ | |
"$OUT" 2>/tmp/ffmpeg.out 1>/dev/null & | |
PID=$! | |
trap "kill $PID 2>/dev/null" EXIT | |
TIME_START=$(date +%s) | |
while kill -0 $PID 2> /dev/null; do | |
LAST_LINE=$(cat /tmp/ffmpeg.out | tail -n1) | |
NOW=$(echo "$LAST_LINE" | sed -ne 's/.*time=\([0-9]*\):\([0-9]*\):\([0-9]*\)\.\([0-9]*\).*/hr=\1; min=\2; sec=\3; msec=\4/p') | |
if [ ! -z "$NOW" ]; then | |
eval "$NOW" | |
hr=$(expr $hr + 0); min=$(expr $min + 0); sec=$(expr $sec + 0); msec=$(expr $msec + 0) | |
((PROGRESS = hr * 3600 + min * 60 + sec)) | |
TIME_NOW=$(date +%s) | |
((TIME_ELAPSED = TIME_NOW - TIME_START)) | |
((SPEED = PROGRESS / TIME_ELAPSED)) | |
((SEC_LEFT = (TOTAL_SEC - PROGRESS) / SPEED)) | |
MIN_LEFT=0 | |
if [ $SEC_LEFT -ge 60 ]; then | |
((MIN_LEFT = SEC_LEFT / 60)) | |
((SEC_LEFT = SEC_LEFT % 60)) | |
fi | |
TIME_LEFT=$(printf "%02d:%02d" $MIN_LEFT $SEC_LEFT) | |
echo "$ERASE progress: ${YELLOW}$PROGRESS${NONE}/$TOTAL_SEC, ETA ${YELLOW}$TIME_LEFT ${NONE}" | |
else | |
echo "$ERASE progress: --" | |
fi | |
sleep 1 | |
done | |
echo "${ERASE}${GREEN}Done${NONE}" | |
fi | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment