Sunday, 19 February 2017

Re-encode audio to AAC, in a bunch of mkv files..

..as fast as bandwidth to the fileserver can allow, running encodes in parallel up to amount of processors. AAC seems compatible with HW decoders everywhere + also with Chromebooks, which invited me to create this:

#!/bin/bash -e

TEMP=/fast/temp
DOWN=2 #allow 1 more than max 'uploads' to keep encoding busy
UP=1 #limit in order to write in a streamlined fashion rather than trashing NAS/FS, due to potential race condition +1 might happen

[[ -z $1 ]] && echo "Usage: $0 <file> [file] [file].." && exit 0
FAACS=$(nproc)
PGID=$$ #limit scope for pgrep
cd "$TEMP"

sleeprnd() { echo $((RANDOM % ($(pgrep -xcg $PGID sleep)+1) +1)); } #random secs between 1 .. amount of sleep processes we're running
waitcount() { while [[ $(pgrep -xcg $PGID $1) -ge $2 ]]; do sleep $(sleeprnd); done; }
re-encode() {
        ORIG="$1"
        BASE="$(basename "$ORIG" .mkv)"
        LOCAL="$BASE"_orig.mkv
        DEST="$(dirname "$ORIG")"/"$BASE"_aac.mkv
        #now wait for ample space to be available @TEMP
        until [[ $(df --output=avail "$TEMP" | tail -n 1) -gt $(( 7 * $(du "$ORIG" | sed -e 's/\t.*//g') )) ]]; do sleep $(sleeprnd); done
        waitcount cp $DOWN; cp -v "$ORIG" "$LOCAL"
        mkvmerge --no-audio "$LOCAL" -o "$BASE"_noaudio.mkv
        for TRACK in $(mkvmerge -i "$LOCAL" | grep ': audio' | sed -e 's/:.*//g' -e 's/.* //g'); do
                mkvextract tracks "$LOCAL" $TRACK:"$BASE"_audio
                waitcount faac $FAACS; ffmpeg -v 0 -i "$BASE"_audio -f wav - \
                        | faac -b 160 - -o "$BASE"_audio_$TRACK.aac &>/dev/null
        done
        mkvmerge "$BASE"_noaudio.mkv "$BASE"_audio_*.aac -o "$BASE".new.mkv
        rm "$BASE"_*
        waitcount cp $UP; cp -v "$BASE".new.mkv "$DEST"
        touch "$DEST" -r "$ORIG"
        #mv "$DEST" "$ORIG"
        echo "$ORIG" >>/dev/shm/ramdisk/log
        rm "$BASE".new.mkv
}

while [[ -n "$1" ]]; do
        re-encode "$1" &
        sleep 1
        shift
done

wait