Created
December 26, 2017 22:00
-
-
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…
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 | |
# 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