Last active
August 29, 2015 13:56
-
-
Save bmatherly/9085903 to your computer and use it in GitHub Desktop.
Normalize media files.
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 | |
declare SRC="" | |
declare DST="" | |
declare -i USE_TIME=0 | |
declare -r WIDTH=1280 | |
declare -r HEIGHT=720 | |
declare -r RATE="60000/1001" | |
declare -r EXT=".mov" | |
function print_help() | |
{ | |
cat <<EOM | |
------------------------------------------------------------------------------- | |
Usage: $(basename $0) [-t] input output | |
-h Print [h]elp and exit. | |
-t Rename output files with modification [t]ime | |
Input and output may be specified as either a file or directory. | |
* If input is a file, it will be normalized to the output file. | |
* If input is a directory, all files inside the directory will be | |
normalized and stored in the output directory. | |
In all cases, an appropriate file extension is added. | |
------------------------------------------------------------------------------- | |
EOM | |
} | |
function parse_args() | |
{ | |
while getopts "hi:o:t" opt | |
do | |
case $opt in | |
h) print_help; exit 0;; | |
i) echo $opt; SRC=$OPTARG;; | |
o) echo $opt; DST=$OPTARG;; | |
t) USE_TIME=1;; | |
*) echo "unknown arg: $opt"; print_help; exit 1;; | |
esac | |
done | |
shift $(($OPTIND - 1)) | |
SRC=$1 | |
DST=$2 | |
} | |
function get_destination_filename() | |
{ | |
local srcname=$1 | |
local dstname="" | |
if [ $USE_TIME -eq 1 ]; then | |
dstname=`date -r "$srcname" "+%Y-%m-%d-%H%M%S"` | |
else | |
# Clean the name of spaces and strage characters | |
dstname=`echo $srcname | tr ' ' '_' | tr -d '[{}(),\!]' | tr -d "\'" | tr '[A-Z]' '[a-z]' | sed 's/_-_/_/g'` | |
# Strip the extension | |
dstname=${dstname%.*} | |
dstname=${dstname##*/} | |
fi | |
echo $dstname$EXT | |
} | |
function normalize_file() | |
{ | |
local src_file="$1" | |
local dst_file="$2" | |
local vf="" | |
local filters="" | |
# Get information about the video | |
vidinfo=`ffmpeg -i "$src_file" -vframes 1 -vf "showinfo" -an -f rawvideo -y /dev/null 2>&1 | grep --max-count=1 showinfo` | |
structure=`echo "$vidinfo" | sed "s/.* i:\([A-Z]*\).*/\1/" | tr -d "[:space:]"` | |
iw=`echo "$vidinfo" | sed "s/.* s:\([1-9][0-9]*\)x\([0-9]*\).*/\1/" | tr -d "[:space:]"` | |
ih=`echo "$vidinfo" | sed "s/.* s:\([1-9][0-9]*\)x\([0-9]*\).*/\2/" | tr -d "[:space:]"` | |
# Deinterlace if necessary | |
if [ "$structure" != "P" ]; then | |
echo "Source is Interlaced" | |
if [ "$filters" != "" ]; then | |
filters=$filters"," | |
fi | |
# Duplicate frames | |
filters=$filters"yadif=1:-1:0" | |
else | |
echo "Source is Progressive" | |
fi | |
# Scale if necessary | |
if [ "$iw" != $WIDTH -o "$ih" != $HEIGHT ]; then | |
echo "Scale $iw x $ih -> $WIDTH x $HEIGHT" | |
if [ "$filters" != "" ]; then | |
filters=$filters"," | |
fi | |
filters=$filters"scale=(iw*sar)*min($WIDTH/(iw*sar)\,$HEIGHT/ih):ih*min($WIDTH/(iw*sar)\,$HEIGHT/ih)" | |
filters=$filters"," | |
# Add bars if AR does not match. Has no effect when they do match. | |
filters=$filters"pad=$WIDTH:$HEIGHT:($WIDTH-iw*min($WIDTH/iw\,$HEIGHT/ih))/2:($HEIGHT-ih*min($WIDTH/iw\,$HEIGHT/ih))/2" | |
fi | |
if [ "$filters" ]; then | |
filters='-vf "'"$filters"'"' | |
fi | |
cmd="ionice -c3 nice -19 ffmpeg -i \"$src_file\" -sn $filters -r $RATE -vcodec dnxhd -vb 220000k -pix_fmt yuv422p -threads 3 -acodec pcm_s16le -ac 2 -ar 48000 \"$dst_file\"" | |
echo "About to run command:" | |
echo "$cmd" | |
eval "$cmd" | |
# Make sure the normalize succeeded. | |
if [ -f "$dst_file" ]; then | |
touch -r "$src_file" "$dst_file" | |
else | |
echo "Normalize Failed" | |
exit 7 | |
fi | |
} | |
parse_args "$@" | |
# Sanity checking, to make sure everything is in order. | |
if [ -z "$SRC" -o -z "$DST" ]; then | |
print_help | |
exit 1 | |
elif [ -f "$SRC" ]; then | |
# Normalize a single file | |
srcfile=$SRC | |
dstfile=$(get_destination_filename "$srcfile") | |
echo "Normalize $srcfile to $dstfile" | |
normalize_file "$srcfile" "$dstfile" | |
elif [ -d "$SRC" ]; then | |
# Normalize all files in a directory | |
if [ ! -d "$DST" ]; then | |
echo "Destination directory does not exist: $DST" | |
exit 2 | |
fi | |
shopt -s nullglob | |
for srcfile in $SRC/* | |
do | |
dstfile=$DST/$(get_destination_filename "$srcfile") | |
echo "Normalize $srcfile to $dstfile" | |
normalize_file "$srcfile" "$dstfile" | |
done | |
else | |
echo "$SRC is not a file or directory" | |
print_help | |
exit 2 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment