Skip to content

Instantly share code, notes, and snippets.

@SpiraMirabilis
Created December 26, 2017 22:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SpiraMirabilis/49ea2835b531b17e66ef2ca360eb6350 to your computer and use it in GitHub Desktop.
Save SpiraMirabilis/49ea2835b531b17e66ef2ca360eb6350 to your computer and use it in GitHub Desktop.
Converts any video to h264 and any audio tracks to AAC, maintins original bitrate. If video is an old xvid/divx that has packed bitstream it will fix that first. Validates the output file (correct codecs and within SECONDS_FUDGE duration or it is rejected) prior to deleting the original. If your ffmpeg doesn't have libfdk compiled in, just chang…
#!/bin/bash
# This will transcode the file given as an argument into h264/aac. It is designed to be used automatically (triggered by inotify or systemd.path)
# so it is very strict on the output. It checks that the output is valid, an that it is the same duration as the input, if it is correct it will
# delete the original.
# If your ffmpeg is not compiled with libfdk_aac, you can change the libfdk_aac to "aac" and use ffmpeg's encoder which is almost as good as libfdk.
# SECONDS_FUDGE is the number of seconds plus or minus that the transcoded video has to be within duration from the original or we reject it
SECONDS_FUDGE=${SECONDS_FUDGE:-15} # 15 seconds is not too bad if we're mainly doing films.
function checkPacked() {
# Older divx/xvid codecs use a terrible non-standard technique that put extra stuff in a frame
# We dont want to transcode without fixing this first
if [ ! -f "$1" ]; then
echo "File not found"
exit 3
fi
info=$(mediainfo "$1")
if echo "$info" | grep -q 'Packed bitstream'; then
filename=$(basename "$1")
extension="${filename##*.}"
filename="${filename%.*}"
tmpn="$filename_tmp.$extension"
ffmpeg -v quiet -i "$1" -codec copy -bsf:v mpeg4_unpack_bframes "$tmpn"
if [ -f "$tmpn" ]; then
rm "$1"
mv "$tmpn" "$1"
echo "$1 - packed bitstream detected and corrected."
else
echo "$1 was packed, but conversion failed!"
fi
fi
}
function removeTempFiles() {
base=$(basename "$1")
noext="${base%.*}*"
rm -rf "/tmp/convert/$noext*"
cnt=$(ls /tmp/convert/ | wc -l)
if [ "$cnt" == "0" ]; then
rmdir /tmp/convert
fi
}
fpath=$1
if [ ! -f "$fpath" ]; then
echo "File not found!"
exit 1
fi
info=$(mediainfo "$fpath")
firstDuration=$(ffmpeg -i "$fpath" 2>&1 | grep Duration | awk '{print $2}' | tr -d ,)
if echo "$info" | grep -Eq '^Format[ ]+: AAC$'; then
if echo "$info" | grep -Eq '^Codec ID[ ]+: avc1$'; then
echo "$fpath already h264/aac"
exit 0
fi
fi
checkPacked "$fpath"
echo "Beginning transcode of $fpath"
if echo "$fpath" | grep -Eq '\/'; then
DIR="${fpath%/*}"
else
DIR="./"
fi
file="${fpath##*/}"
fpath2="/tmp/convert/$file"
mkdir -p /tmp/convert/
cp "$fpath" "$fpath2"
ffmpeg -i "$fpath2" -v quiet -c:v libx264 -c:a libfdk_aac $2 -map 0 "${fpath2%.*}.mp4"
if [ ! -f "${fpath2%.*}.mp4" ]; then
echo "MP4 wasn't generated!"
exit 1
else
if [ "$EUID" == "0" ]; then
# if we're running as root that probably means we want to chown the files afterwards
chown "${MEDIA_OWNER:-mdm}:${MEDIA_GROUP:-82}" "${fpath2%.*}.mp4"
fi
file2="${fpath2%.*}.mp4"
info=$(mediainfo "$file2")
if echo "$info" | grep -Eq '^Format[ ]+: AAC$'; then
if echo "$info" | grep -Eq '^Codec ID[ ]+: avc1$'; then
echo "Validating $file2..."
secondDuration=$(ffmpeg -i "$file2" 2>&1 | grep Duration | awk '{print $2}' | tr -d ,)
# convert to unixtime so we can cheat and determine the difference in seconds
SEC1=`date +%s -d ${firstDuration}`
SEC2=`date +%s -d ${secondDuration}`
DIFFSEC=`expr ${SEC1} - ${SEC2}`
# some videos appear to be a few seconds different in duration, but otherwise encoded correctly.
# we can adjust SECONDS_FUDGE to tighten this check
if [ "$DIFFSEC" -gt "$(echo -$SECONDS_FUDGE | bc)" ]; then
if [ "${DIFFSEC}" -lt "${SECONDS_FUDGE}" ]; then
echo "$fpath -> ${fpath%.*}.mp4 transcode verified successful, removing $fpath "
rm "$fpath"
mv "${fpath2%.*}.mp4" "$DIR"
removeTempFiles $fpath
exit 0
fi
fi
echo "Transcode has a $DIFFSEC seconds difference between the original's duration! REJECT!"
removeTempFiles $fpath
exit 4
fi
fi
echo "MP4 generated, but it is not h264/aac ??"
removeTempFiles $fpath
exit 2
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment