Skip to content

Instantly share code, notes, and snippets.

@atroche
Created April 15, 2019 02:31
Show Gist options
  • Save atroche/5a3135b770264e62295bd2184dafba9b to your computer and use it in GitHub Desktop.
Save atroche/5a3135b770264e62295bd2184dafba9b to your computer and use it in GitHub Desktop.
#!/bin/bash -e
set -e
# defaults for all configuration values
ENC="ffmpeg"
CRF=24
OPTS="-map 0 -c:v libx265 -pix_fmt yuv420p10le -preset fast -x265-params crf=${CRF}:aq-mode=3 -c:a libvorbis -aq 5"
# This is to split out and copy attachment streams, like subtitles
# and fonts, so they only get copied once.
DATA_OPTS="-map 0 -c:s copy -c:t copy -c:d copy -vn -an"
SUFFIX="_new.mkv"
SERVERS=":"
LEN=300
OUTDIR='./tmp'
VERBOSE="error"
# override defaults in a ~/.dverc file
if [ -f ~/.dverc ]; then
source ~/.dverc
fi
function on_finish() {
# echo "Cleaning up temporary working files"
# cd "$CWD"
# rm -rf "${OUTDIR}"/
# echo "Finished cleaning"
echo "done"
}
function usage() {
cat << EOF
usage: $0 [options] filename
This script breaks a video file up into chunks and encodes them in parallel via SSH on
multiple hosts.
OPTIONS:
-h this help message.
-l comma separated list of hosts to use to encode. (default=${SERVERS})
-t rough length of individual video chunks, in seconds. (default=${LEN})
-o encoding options. (default=${OPTS})
-s output file suffix. (default=${SUFFIX})
-q video encoding quality, shortcut to use default encoding options with
a different CRF. (default=${CRF})
-v verbose job output. (default=false)
EOF
}
# check all required helper utils
function checkpaths() {
for cmd in parallel ffmpeg; do
if ! CMD=`which $cmd`; then
echo "$cmd not found in local path."
exit 1
fi
done
}
while getopts “hl:t:o:s:q:v” OPTION; do
case $OPTION in
h)
usage
exit 1
;;
l)
SERVERS="$OPTARG"
;;
t)
LEN="$OPTARG"
;;
q)
CRF="$OPTARG"
OPTS="-map 0 -c:v libx265 -pix_fmt yuv420p10le -preset fast -x265-params crf=${CRF}:aq-mode=3 -c:a libvorbis -aq 5"
;;
o)
OPTS="$OPTARG"
;;
s)
SUFFIX="$OPTARG"
;;
v)
VERBOSE="info"
;;
?)
usage
exit
;;
esac
done
shift $((OPTIND-1))
if [ $# -lt 1 ]; then
usage
exit 1
fi
CWD=`pwd`
trap on_finish EXIT
checkpaths
if ! mkdir -p ${OUTDIR}; then
echo "Couldn't create temp chunk output dir ${OUTDIR}."
exit 1
fi
echo "Creating chunks to encode"
if [[ "$1" == *".AVI" || "$1" == *".avi" ]]; then
$ENC -fflags +genpts -i "$1" -map 0:a -map 0:v -codec copy -f segment -segment_time $LEN -segment_format matroska -v ${VERBOSE} "${OUTDIR}/chunk-%03d.orig"
else
$ENC -i "$1" -map 0:a -map 0:v -codec copy -f segment -segment_time $LEN -segment_format matroska -v ${VERBOSE} "${OUTDIR}/chunk-%03d.orig"
fi
echo "Copying file metadata"
DATA_IN="-i data.enc -map 1"
${ENC} -y -v ${VERBOSE} -i "$1" ${DATA_OPTS} -f matroska "${OUTDIR}/data.enc" ||
DATA_IN=""
cd "$OUTDIR"
ls
echo "Running parallel encoding jobs"
PAR_OPTS="--verbose --no-notice --gnu -j 1 --eta --retries 2 --nice 10"
ENC_OPTS="-y -v ${VERBOSE} -i {} ${OPTS} -f matroska {.}.enc"
echo $PAR_OPTS
echo $ENC
echo $ENC_OPTS
echo "doing par"
parallel ${PAR_OPTS} ${ENC} ${ENC_OPTS} ::: ./chunk-*.orig
echo "i did par"
echo "Combining chunks into final video file"
echo "ffconcat version 1.0" > concat.txt
for f in `ls chunk-*.enc | sort`; do
echo "file $f" >> concat.txt
done
BASE=`basename "$1"`
OUTFILE="${CWD}"/"${BASE%.*}${SUFFIX}"
${ENC} -y -v ${VERBOSE} -f concat -i concat.txt ${DATA_IN} -map 0 -f matroska -c copy "${OUTFILE}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment