Skip to content

Instantly share code, notes, and snippets.

@schlomo
Last active April 13, 2018 10:46
Show Gist options
  • Save schlomo/6697076 to your computer and use it in GitHub Desktop.
Save schlomo/6697076 to your computer and use it in GitHub Desktop.
Convert videos to MP4 with HandBrake (http://handbrake.fr)
#!/bin/bash
#
# search for .m2ts, .mov, .mp4 files and convert them to .m4v files with HandBrake
# search in current dir or in files/folders given as args
if [[ "$*" == *--help* ]] ; then
cat <<EOF
Usage: $0 [path or file] ...
Convert all .m2ts, .mov, .mp4 videos in given paths or files
(or in $(pwd)) to 3 .m4v (with H264 and AAC) videos:
For iPod (320p), 720p and full resolution of the input video.
Uses HandBrakeCLI (http://handbrake.fr) for actual video conversion.
Licensed under the GNU General Public License.
Written by Schlomo Schapiro
EOF
exit 1
fi
# we store a configuration matrix connecting file suffixes to HandBrake profiles.
# for each suffix we create a corresponding file
HB_CONFIG_MATRIX=(
.ipod.m4v:"-e x264 -b 700 -5 -2 -T -O -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 -f mp4 -I -X 320 -m -x level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:subme=6:8x8dct=0:trellis=0"
.720.m4v:"-e x264 -q 20.0 -5 -4 -O -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 -f mp4 -X 1280 --crop 0:0:0:0 -m -x ref=2:bframes=2:subme=6:mixed-refs=0:weightb=0:trellis=0:me=umh"
.full.m4v:"-e x264 -q 20.0 -5 -4 -O -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 -f mp4 --crop 0:0:0:0 -m -x ref=2:bframes=2:subme=6:mixed-refs=0:weightb=0:trellis=0:me=umh"
)
die() {
echo 1>&2 "ERROR: $@"
exit 1
}
getsize() {
# get size of $1
read size junk < <(du -h "$1") || return 1
echo $size
}
print_seconds() {
printf "%02d:%02d:%02d" $(($1/60/60)) $((($1/60)%60)) $(($1%60))
}
type -p HandBrakeCLI >/dev/null || die "Could not find HandBrakeCLI in PATH"
WORK=$(mktemp -t -d video_converter-XXXXXXXXXXX)
trap '$KEEPWORKDIR rm -Rf $WORK' 0
trap "" SIGSEGV SIGFPE
mkdir -p $WORK/.config/ghb
touch $WORK/.config/ghb/presets
export HOME=$WORK # fake homedir for HandBrakeCLI
let video_converted_count=0
#set -x
JOBS=()
let jobcount=0
# read videos into array
mapfile -t VIDEOS < <( find "$@" -path "*.Trash*" -prune -o -type f \( -iname \*.m2ts -o -iname \*.mov -o -iname \*.mp4 \) -printf "%H/%P\n" )
for video_source in "${VIDEOS[@]}"; do
if [[ "$video_source" == *:* ]] ; then
# do not support filenames with : in them (unlikely as : is illegal on Windows)
die "Invalid character ':' found in '$video_source'"
fi
#echo "Considering $video_source"
for jobdef in "${HB_CONFIG_MATRIX[@]}" ; do
JOBS[$jobcount]="$video_source:$jobdef"
let jobcount++
done
done
let tries=1 max_tries=5
let current=0
while test $current -lt ${#JOBS[@]} ; do
IFS=: read video_source suffix profile <<<"${JOBS[$current]}"
org_size="$(getsize "$video_source")" || die "Could not determine size of '$video_source'"
video_dest_base="${video_source%.*}" # remove last suffix
video_dest="$video_dest_base$suffix"
log_file="$WORK/${video_dest_base////_}.log" # convert / to _ in log file name
#### enable these for dummy mode
#echo "Would convert $video_source to $video_dest"
#let tries=max_tries
#continue
if test -s "$video_dest" ; then
# echo "Skipping '$video_dest'"
let tries=max_tries
else
let start=SECONDS
# initialize log file with HandBrakeCLI options
declare -p video_source video_dest profile >"$log_file"
#
# protect the outer find | while read loop from HandBrakeCLI ! -------------------------------------\
# |
# \./
if HandBrakeCLI -v 1 $profile -i "$video_source" -o "$video_dest.video_converter" >>"$log_file" 2>&1 </dev/null && [[ -s "$video_dest.video_converter" ]] ; then
let conversion_time=SECONDS-start
mv "$video_dest.video_converter" "$video_dest" || die "Could not move '$video_dest.video_converter' to '$video_dest'"
new_size="$(getsize "$video_dest")" || die "Could not determine size of '$video_dest'"
rm -f "$log_file"
touch -c -r "$video_source" "$video_dest" # keep mtime of orginial file
echo "Converted ($org_size -> $new_size) '$video_dest' in $(print_seconds $conversion_time)"
let video_converted_count++ tries=max_tries
else
echo -n "HandBrakeCLI '$video_source' failed with profile '$profile'."
if [ $tries -lt $max_tries ] ; then
echo " Retrying $tries of $max_tries"
else
echo " Reached maximum $max_tries tries, skipping!"
echo
echo " Log file of last conversion attempt:"
sed -e 's/^/ /' "$log_file"
fi
rm -f "$video_dest.video_converter" "$log_file"
fi
fi
if test $tries -ge $max_tries ; then
let current+=1 tries=1
else
let tries+=1
fi
done
if [ $video_converted_count -gt 0 ] ; then
echo "Converted $video_converted_count videos in $(print_seconds $SECONDS)"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment