forked from NMAAHC/nmaahcmm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
makeDer
executable file
·156 lines (143 loc) · 7.87 KB
/
makeDer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/usr/bin/env bash
# a script to create a H264 derivative of a given input
# unlike makeDer, this script asks the operator to select a CRF value and preset encoding speed
# load nmaahcmmfunctions into this script
SCRIPT_PATH="${0%/*}"
. "${SCRIPT_PATH}/nmaahcmmfunctions"
[[ -f "${SCRIPT_PATH}/nmaahcmmfunctions" ]] || { echo "Missing '${SCRIPT_PATH}/nmaahcmmfunctions'. Exiting." ; exit 1 ;};
_initialize_make # safe script termination process defined in nmaahcmmfunctions
DEPENDENCIES=(ffmpeg) # list dependencies required by script
_check_dependencies "${DEPENDENCIES[@]}" # defined in nmaahcmmfunctions
RELATIVEPATH="derivatives"
EXTENSION="mp4"
### FUNCTIONS
# this function needs to be defined before the getopts loop as it is used within that loop
_check_outputdir_forced(){
if [[ ! -d "${OUTPUTDIR_FORCED}" ]] ; then
_report -rt "The directory, ${OUTPUTDIR_FORCED}, does not exist. Can not write the output of $(basename "${0}")."
exit 1
else
_report -g "Output directory is: ${OUTPUTDIR_FORCED}"
#_writeerrorlog "_check_outputdir_forced" "The specified directory does not exist, and the output could not be delivered."
fi
}
### USAGE
_usage(){
echo
echo "$(basename "${0}")"
echo "This application will create a high quality h264 file (suitable for uploading to YouTube). It takes a video file or package as input."
echo "If the input is a file, the output will be named after the file's containing directory, which is assumed to be the media ID."
echo "If the input is a directory, the script will create derivatives for all .mov files in the directory, and the output files will be named after those files."
echo "You can set the directory where the output should be sent with the -o flag. If you don't set the directory, the script will create a directory called 'derivatives' within the input directory or containing directory and send the files there."
echo "Usage: $(basename ${0}) [ -o /output/directory/path/ ] fileorpackage1 [ fileorpackage2 ...]"
echo
exit
}
[ "${#}" = 0 ] && _usage # if the command is run with no arguments then _usage is called
# getopts loop
OPTIND=1
while getopts ":o:h" OPT ; do
case "${OPT}" in
o) OUTPUTDIR_FORCED="${OPTARG}" && _check_outputdir_forced ;;
h) _usage ;; # if the operator runs "[scriptname] -h" then the _usage text above will display in the terminal
*) echo "Invalid option: -$OPTARG" ; _usage ; exit 1 ;;
esac
done
shift $(( ${OPTIND} - 1 ))
## SCRIPT ACTIONS
# log script beginning
_log -b
cat <<-EOF
A CRF value needs specified.
The range of the quantizer scale is 0-51, where 0 is lossless, 23 is default, and 51 is worst possible.
A lower value is a higher quality and a subjectively useful range is 18-28.
Consider 18 to be visually lossless or nearly so: it should look the same or nearly the same as the input,
but it is not technically lossless.
The range is exponential, so increasing the CRF value +6 is roughly half the bitrate, while -6 is roughly twice the bitrate.
General usage is to choose the highest CRF value that still provides an acceptable quality.
If the output looks good, then try a higher value. If it looks bad then choose a lower value.
EOF
echo
_report -b "Please enter a CRF value : "
read CRFVALUE
echo
cat <<-EOF
A preset encoding speed needs specified.
A preset is a collection of options that will provide a certain encoding speed to compression ratio.
A slower preset will provide better compression (compression is quality per filesize).
This means that, for example, if you target a certain file size or constant bit rate,
you will achieve better quality with a slower preset.
Similarly, for constant quality encoding, you will simply save bitrate by choosing a slower preset.
The general guideline is to use the slowest preset that you have patience for.
Current presets in descending order of speed are:
EOF
_report -b "ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow"
echo
_report -b "Please enter a preset speed: "
read PRESETSPEED
while [ "${*}" != "" ] ; do
#set $INPUT as the first argument sent to script
INPUT="${1}"
# set output directory, create it, and confirm it created successfully before proceeding
if [[ -z "${OUTPUTDIR_FORCED}" ]]; then # if the operator did not specify an output directory, do the following
if [[ -f "${INPUT}" ]]; then
OUTPUT_DIR="${INPUT%%.*}/${RELATIVEPATH}" # output subdirectory will be created in same directory as the input file, and named after that file
fi
if [[ -d "${INPUT}" ]]; then
OUTPUT_DIR="${INPUT}/${RELATIVEPATH}" # output will be sent to a subdirectory of the input directory
fi
else
OUTPUT_DIR="${OUTPUTDIR_FORCED}"
fi
mkdir -p "${OUTPUT_DIR}"
if [[ -d "${OUTPUT_DIR}" ]] ; then
_report -g "Output directory is: ${OUTPUT_DIR}"
else
_report -rt "ERROR: ${FOLDER} does not exist. Exiting..."
_log -a "Process terminated by script (no directory at requested location)."
exit 1
fi
# run ffmpeg command on $INPUT and send output to a file at location $OUTPUT
# if input is a file -> script sets media ID and output filename based on input filename
# (if input is a directory -> script finds .mov files in the input directory, and derivatives are created with the same names as the files in the input directory)
if [[ -f "${INPUT}" ]]; then
#set $MEDIAID to basename of $INPUT with extension stripped
MEDIAID=$(basename "${INPUT}" | cut -d. -f1)
_report -g "Media ID is: ${MEDIAID}"
OUTPUT="${OUTPUT_DIR}/${MEDIAID%.*}.${EXTENSION}"
_report -g "Output filename is: ${OUTPUT}"
if [[ -s "${OUTPUT}" ]] ; then
#check to see if $OUTPUT exists
_report -rt "WARNING: ${OUTPUT} already exists, skipping transcode"
_report -rt "Moving to next file if present..."
else
_report -g "Making .mp4 derivative of ${INPUT}"
ffmpeg -vsync 0 -nostdin -v info -hide_banner -stats -i "${INPUT}" -movflags faststart -pix_fmt yuv420p -c:v libx264 -crf "${CRFVALUE}" -preset "${PRESETSPEED}" -maxrate 8000k -bufsize 1835k -c:a aac -strict -2 -b:a 384k -f mp4 "${OUTPUT}"
fi
elif [[ -d "${INPUT}" ]]; then
_report -g "Making .mp4 derivatives for files in ${INPUT}"
for FILE in $(find "${INPUT}" -iname "*.mov") ; do
OUTPUT="${OUTPUT_DIR}/$(basename ${FILE%.*}).${EXTENSION}"
echo "FILE is $FILE, basename is $(basename ${FILE}), output is $OUTPUT"
if [[ -s "${OUTPUT}" ]] ; then
#check to see if $OUTPUT exists
_report -rt "WARNING: ${OUTPUT} already exists, skipping transcode"
_report -rt "Moving to next file if present..."
else
ffmpeg -vsync 0 -nostdin -v info -hide_banner -stats -i "${FILE}" -movflags faststart -pix_fmt yuv420p -c:v libx264 -crf "${CRFVALUE}" -preset "${PRESETSPEED}" -maxrate 8000k -bufsize 1835k -c:a aac -strict -2 -b:a 384k -f mp4 "${OUTPUT}"
fi
done
fi
# rename file to indicate derivative
# works by finding all mp4s in the output directory that have "PM" or "DER_01" in their filename; the "if" executes if any files matching those patterns are found (i.e. if the find statement executes to non-empty "-n")
if [[ -n $(find "${OUTPUT_DIR}" -type f -iname "*PM*.mp4" ) ]]; then
rename 's/PM/DER_02/' *.mp4 && _report -g "Updated derivative filename to reflect current name : PM to DER_02"
fi
if [[ -n $(find "${OUTPUT_DIR}" -type f -iname "*DER_01*.mp4" ) ]]; then
rename 's/DER_01/DER_03/' *.mp4 && _report -g "Updated derivative filename to reflect current name conventions: DER_01 to DER_03"
fi
shift
done
# log script ending
_log -e
_report -g "makeDer process complete."