-
-
Save lisamelton/5734177 to your computer and use it in GitHub Desktop.
#!/bin/bash | |
# encode.sh | |
# | |
# Copyright (c) 2013 Don Melton | |
# | |
# This version published on June 7, 2013. | |
# | |
# Re-encode video files in a format suitable for playback on Apple TV, Roku 3, | |
# iOS, OS X, etc. | |
# | |
# Input is assumed to be a single file readable by HandBrakeCLI and mediainfo, | |
# e.g. just about any .mkv, .avi, .mpg, etc. file. | |
# | |
# The script automatically calculates output video bitrate based on input. For | |
# Blu-ray Disc-quality input that's always 5000 Kbps. For DVD-quality input | |
# that's always 1800 Kbps. For other files that will vary. | |
# | |
# The script also automatically calculates video frame rates and audio channel | |
# configuration. | |
# | |
# If the input contains a VobSub (DVD-style) or PGS (Blu-ray Disc-style) | |
# subtitle, then it is burned into the video. | |
# | |
# Optional frame rate overrides and soft subtitles in .srt format are read | |
# from separate fixed locations in the `$frame_rates_location` and | |
# `$subtitles_location` variables defined below. Edit this script to redefine | |
# them. | |
# | |
# If your input file is named "foobar.mkv" then the optional frame rate file | |
# should be named "foobar.txt". And all it should contain is the frame rate | |
# number, e.g. "25" followed by a carriage return. | |
# | |
# If your input file is named "foobar.mkv" then the optional soft subtitle | |
# file should be named "foobar.srt". | |
# | |
# Output is an MP4 container with H.264 video, AAC audio and possibly AC-3 | |
# audio if the input has more than two channels. | |
# | |
# No scaling or cropping is performed on the output. This is a good thing. | |
# | |
# The output .mp4 file and a companion .log file are written to the current | |
# directory. | |
# | |
# This script depends on two separate command line tools: | |
# | |
# HandBrakeCLI http://handbrake.fr/ | |
# mediainfo http://mediainfo.sourceforge.net/ | |
# | |
# Make sure both are in your `$PATH` or redefine the variables below. | |
# | |
# Usage: | |
# | |
# ./encode.sh [input file] | |
# | |
die() { | |
echo "$program: $1" >&2 | |
exit ${2:-1} | |
} | |
escape_string() { | |
echo "$1" | sed "s/'/'\\\''/g;/ /s/^\(.*\)$/'\1'/" | |
} | |
readonly program="$(basename "$0")" | |
readonly input="$1" | |
if [ ! "$input" ]; then | |
die 'too few arguments' | |
fi | |
handbrake="HandBrakeCLI" | |
mediainfo="mediainfo" | |
frame_rates_location="/path/to/Frame Rates" | |
subtitles_location="/path/to/Subtitles" | |
# My advice is: do NOT change these HandBrake options. I've encoded over 300 | |
# Blu-ray Discs, 30 DVDs and numerous other files with these settings and | |
# they've never let me down. | |
handbrake_options="--markers --large-file --encoder x264 --encopts vbv-maxrate=25000:vbv-bufsize=31250:ratetol=inf --crop 0:0:0:0 --strict-anamorphic" | |
width="$(mediainfo --Inform='Video;%Width%' "$input")" | |
height="$(mediainfo --Inform='Video;%Height%' "$input")" | |
if (($width > 1280)) || (($height > 720)); then | |
max_bitrate="5000" | |
elif (($width > 720)) || (($height > 576)); then | |
max_bitrate="4000" | |
else | |
max_bitrate="1800" | |
fi | |
min_bitrate="$((max_bitrate / 2))" | |
bitrate="$(mediainfo --Inform='Video;%BitRate%' "$input")" | |
if [ ! "$bitrate" ]; then | |
bitrate="$(mediainfo --Inform='General;%OverallBitRate%' "$input")" | |
bitrate="$(((bitrate / 10) * 9))" | |
fi | |
if [ "$bitrate" ]; then | |
bitrate="$(((bitrate / 5) * 4))" | |
bitrate="$((bitrate / 1000))" | |
bitrate="$(((bitrate / 100) * 100))" | |
if (($bitrate > $max_bitrate)); then | |
bitrate="$max_bitrate" | |
elif (($bitrate < $min_bitrate)); then | |
bitrate="$min_bitrate" | |
fi | |
else | |
bitrate="$min_bitrate" | |
fi | |
handbrake_options="$handbrake_options --vb $bitrate" | |
frame_rate="$(mediainfo --Inform='Video;%FrameRate_Original%' "$input")" | |
if [ ! "$frame_rate" ]; then | |
frame_rate="$(mediainfo --Inform='Video;%FrameRate%' "$input")" | |
fi | |
frame_rate_file="$(basename "$input")" | |
frame_rate_file="$frame_rates_location/${frame_rate_file%\.[^.]*}.txt" | |
if [ -f "$frame_rate_file" ]; then | |
handbrake_options="$handbrake_options --rate $(cat "$frame_rate_file")" | |
elif [ "$frame_rate" == '29.970' ]; then | |
handbrake_options="$handbrake_options --rate 23.976" | |
else | |
handbrake_options="$handbrake_options --rate 30 --pfr" | |
fi | |
channels="$(mediainfo --Inform='Audio;%Channels%' "$input" | sed 's/[^0-9].*$//')" | |
if (($channels > 2)); then | |
handbrake_options="$handbrake_options --aencoder ca_aac,copy:ac3" | |
elif [ "$(mediainfo --Inform='General;%Audio_Format_List%' "$input" | sed 's| /.*||')" == 'AAC' ]; then | |
handbrake_options="$handbrake_options --aencoder copy:aac" | |
fi | |
if [ "$frame_rate" == '29.970' ]; then | |
handbrake_options="$handbrake_options --detelecine" | |
fi | |
srt_file="$(basename "$input")" | |
srt_file="$subtitles_location/${srt_file%\.[^.]*}.srt" | |
if [ -f "$srt_file" ]; then | |
subtitle_format="$(mediainfo --Inform='Text;%Format%' "$input" | sed q)" | |
if [ "$subtitle_format" == 'VobSub' ] || [ "$subtitle_format" == 'PGS' ]; then | |
handbrake_options="$handbrake_options --subtitle 1 --subtitle-burned" | |
else | |
tmp="" | |
trap '[ "$tmp" ] && rm -rf "$tmp"' 0 | |
trap '[ "$tmp" ] && rm -rf "$tmp"; exit 1' SIGHUP SIGINT SIGQUIT SIGTERM | |
tmp="/tmp/${program}.$$" | |
mkdir -m 700 "$tmp" || exit 1 | |
temporary_srt_file="$tmp/subtitle.srt" | |
cp "$srt_file" "$temporary_srt_file" || exit 1 | |
handbrake_options="$handbrake_options --srt-file $(escape_string "$temporary_srt_file") --srt-codeset UTF-8 --srt-lang eng --srt-default 1" | |
fi | |
fi | |
output="$(basename "$input")" | |
output="${output%\.[^.]*}.mp4" | |
echo "Encoding: $input" >&2 | |
time "$handbrake" \ | |
$handbrake_options \ | |
--input "$input" \ | |
--output "$output" \ | |
2>&1 | tee -a "${output}.log" |
Hi, is it possible to get this to batch convert a load of .mpg files in a directory without having to run the script with each video filename on the end?
I really like the script, however it looks like it uses the first audio track from what I can tell. Some of my videos have a different language as the first audio track than the one I want. I'm looking to modify it to pull the English audio track and copy DTS with a fall back of aac.
I found another script on the Internet that would encode everything in a given folder. I modified it to call this script rather than HandBrakeCLI directly. This allowed me to do all files using this script. Now to get the right language and foreign audio scan.
racinrandall, can you give us your script?
For people who need to batch run:
find . -maxdepth 1 -type f -iname "*.*" -exec encode.sh {} \;
You can replace *.*
with file pattern
racinrandall - care to share your script?
great script.
However, I am getting the following error:
: not found
: not found
encode.sh: 58: Syntax error: Bad fd number
I saved the script and called as:
sh encode.sh /path/to/video_file.m2ts
I am using FreeNas
which is a BSD
based distro
To preserve copying files (in this case all m4v and mkv files) found recursively into the same directory:
$ find . -type f -path *.m4v -o -path *.mkv -exec encode.sh {} ;
update encode.sh lines 179-181
outputdir=$(dirname "${input}")
output="$(basename "$input")"
output="${outputdir}/${output%.[^.]*}.mp4"
Hi, i using Ubuntu 14.04 LTS - what dependencies need to be installed on my system?
I've always installed HandbrakeCLI & mediainfo (with ffmpeg, ..), when i try convert my mkv file:
[15:30:56] add_ffmpeg_subtitle: unknown subtitle stream type: 0x53526970
[15:30:56] scan: decoding previews for title 1
thanks,
Dennis