Handbrake Script

mythbrake.sh

#!/bin/sh

# Commercial Removal and transcode script for MythTV, updated 11/10/14
# Input arguments are passed to this user job from mythtv-setup
# Invoke using: postProcessRecording.sh %DIR% %FILE% %CHANID% %STARTTIMEUTC%
#
# Pre-requisites:
# 0. A working MythTV backend setup
# 1. HandBrakeCLI installed.  If you need to install this on a Ubuntu system,
#    try:  sudo apt-get install handbrake-cli
# 2. Your MythTV database username and password:
#    -- Add these to DBUSER and DBPASSWD lines below.  Keep quotes.
#
# Script functions:
# 0. Invoked as a user-job after a MythTV recording completes
# 1. Query database to check if invoked for a commercial-free channel
# 2. If commercial-free channel, go to step 7
# 3. Flag commercials using "All" methods, copy flagged commercials to cutlist
# 4. Lossless transcode to remove commercials from the file
# 5. Rebuild the seek table. Clear cutlist
# 6. Update database to point to recording with no commercials
# 7. Remove stale bookmarking and seek information from the database
# 8. Use Handbrake to transcode recording to H.264 (MPEG-4):
#    -- preserve original audio track (5.1, dts etc.)
#    -- preserve subtitles
#    -- Use x264 encoder for HD-quality video with much reduced file-size
#    -- deinterlace video if necessary
#    -- create .mp4 file format compatible with Roku or Apple/Android devices
# 9. Update database to point to the new .mp4 transcoded file
# 10. Rebuild seektable for new .mp4 transcoded file
# 11. Remove original recording and cleanup temp files

# Update these based on your setup
#
DBUSER="mythtv"
DBPASSWD="6jaw0P3s"

# Input arguments
#
VIDEODIR=$1 # %DIR%
INFILE=$2   # %FILE%
CHAN=$3     # %CHANID%
START=$4    # %STARTTIMEUTC%

# Locally generated variables
#
# Change extension to .mp4
#OUTFILE=`echo "$2" | sed s/\.mpg/\.mp4/g | sed s/\.ts/\.mp4/g`
OUTFILE=`echo "$2"  | sed s/\.ts/\.mp4/g`
TEMPDIR="/tmp"
MYPID=$$

# Run at a lower priority
renice 19 $MYPID
ionice -c 3 -p $MYPID

# Sanity check usage and file existence
if [ -z "$VIDEODIR" -o -z "$INFILE" -o -z "$CHAN" -o -z "$START" ]; then
   echo "Usage: $0 <VideoDir> <FileName> <ChannelID> <StartTime>\r" >> pp.log
   exit 5
fi
if [ ! -f "$VIDEODIR/$INFILE" ]; then
   echo "$0: File does not exist: $VIDEODIR/$INFILE\r"  >> pp.log
   exit 6
fi

# Work from a temporary directory
mkdir $TEMPDIR/postProcess-$MYPID
cd $TEMPDIR/postProcess-$MYPID

# Only go through commercial flagging if this isn't a commercial-free
# channel.  This can be determined by querying the channel table.
COMMFREE=0
mkfifo sqlpipe.$MYPID            # needed to preserve scope of COMMFREE variable
mysql --user=$DBUSER --password=$DBPASSWD mythconverg --column-names=0 -ss \
   -e 'SELECT chanid FROM channel WHERE commmethod='-2';' > sqlpipe.$MYPID &

while read -r LINE
do
   if [ "$CHAN" -eq "$LINE" ]; then
      COMMFREE=1
      echo "$0: Commercial-free channel. Skipping commercial flagging.\r"  >> pp.log
   fi
done < sqlpipe.$MYPID

if [ $COMMFREE -eq 0 ]; then
   # Flag commercials, copy the flagged commercials to the cutlist, and
   # transcode the video to remove the commercials from the file.
   mythcommflag --chanid $CHAN --starttime $START --method 7 --quiet
   ERROR=$?
   if [ $ERROR -gt 126 ]; then
      echo "Commercial flagging failed for ${INFILE} with error $ERROR\r" >> pp.log
      exit $ERROR
   fi

   echo -n "$0: Generating cutlist for $INFILE...\r" > pp.log
   mythutil --gencutlist --chanid $CHAN --starttime $START --quiet
   ERROR=$?
   if [ $ERROR -ne 0 ]; then
      echo "Copying cutlist failed for ${INFILE} with error $ERROR\r"  >> pp.log
      exit $ERROR
   fi
   echo -n "$0: Removing commercials... \r"  >> pp.log

   # Remove commercials in a .tmp file, replace original recording
   echo "starting mythtranscode\r"  >> pp.log
#   mythtranscode --honorcutlist --mpeg2 --showprogress -i $VIDEODIR/$INFILE \
   mythtranscode  --mpeg2 --showprogress -i $VIDEODIR/$INFILE \
      -o $TEMPDIR/postProcess-$MYPID/$INFILE.tmp --quiet
   mv -f $TEMPDIR/postProcess-$MYPID/$INFILE.tmp $VIDEODIR/$INFILE

   echo "replaced $INFILE.tmp with $INFILE. Rebuilding seek table...\r "  >> pp.log
   # This will rebuild the seek table
   mythcommflag --chanid $CHAN --starttime $START --rebuild --quiet
   ERROR=$?
   if [ $ERROR -ne 0 ]; then
      echo "Rebuilding seek list failed for ${INFILE} with error $ERROR\r"  >> pp.log
      exit $ERROR
   fi

   # Remove the cutlist from the program
   #
   mythutil --clearcutlist --chanid $CHAN --starttime $START --quiet
   ERROR=$?

   # If successful, fix up the database to point to the transcoded mpeg-2 file
   if [ $ERROR -eq 0 ]; then
      echo "UPDATE recorded SET cutlist=0, \
      filesize = $(ls -l $VIDEODIR/$INFILE | awk '{print $5}') \
      WHERE basename = '$INFILE';" > update-db-$MYPID.sql
      mysql --user=$DBUSER --password=$DBPASSWD mythconverg \
      < update-db-$MYPID.sql

   else
      echo "Clearing cutlist failed for ${INFILE} with error $ERROR\r"  >> pp.log
      rm -f $VIDEODIR/$INFILE.tmp
      exit $ERROR
   fi
fi                                        # ENDIF for channels with commercials

# Remove stale bookmarking and seeking info in the database
echo "DELETE FROM recordedseek WHERE chanid='$CHAN' AND \
   starttime='$START';" > update-db-$MYPID.sql
mysql --user=$DBUSER --password=$DBPASSWD mythconverg < update-db-$MYPID.sql
echo "DELETE FROM recordedmarkup WHERE chanid='$CHAN' AND \
   starttime='$START';" > update-db-$MYPID.sql
mysql --user=$DBUSER --password=$DBPASSWD mythconverg < update-db-$MYPID.sql

# Transcode the file to .mp4
echo "Transcoding $INFILE to $OUTFILE\r" >> pp.log
#HandBrakeCLI -i $VIDEODIR/$INFILE -o $VIDEODIR/$OUTFILE --format mp4 \
#   --no-dvdnav --optimize  --markers --encoder x264 \
#   --h264-profile main --x264-preset medium --audio 1 --aencoder copy \
#   --audio-fallback aac --arate Auto --ab 160 --maxWidth 1280 \
#   --maxHeight 720 --loose-anamorphic --loose-crop --modulus 2 --decomb \
#   --quality 20 --rate 30 --pfr --verbose 0 2 > hb-log$MYPID.txt

HandBrakeCLI -i $VIDEODIR/$INFILE -o $VIDEODIR/$OUTFILE -e x264 -q 21 -O \
    -r 30 --pfr -x ref=6:bframes=5:vbv-maxrate=62000:vbv-bufsize=62000 \
    -X 720 --decomb --loose-anamorphic --modulus 2 --x264-tune film \
#    --x264-preset medium --h264-profile high --h264-level 4.1 -a 1,1 \
    --x264-preset medium --h264-profile main --h264-level 4.1 -a 1,1 \
    -E copy:ac3,faac -B auto,160 -R auto,auto -6 auto,dpl2 \
    --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 \
    -f mp4 --verbose 1 2 > hb-log$MYPID.txt

# Update the database to point to the transcoded file
echo "UPDATE recorded SET basename='$OUTFILE', \
   filesize = $(ls -l $VIDEODIR/$OUTFILE | awk '{print $5}'), \
   transcoded='1' WHERE chanid='$CHAN' AND \
   starttime='$START';" > update-db-$MYPID.sql
mysql --user=$DBUSER --password=$DBPASSWD mythconverg < update-db-$MYPID.sql

# Rebuild the seektable for new MP4 file
mythcommflag --chanid $CHAN --starttime $START --rebuild --quiet
ERROR=$?
if [ $ERROR -ne 0 ]; then
   echo "Rebuilding seek list failed for ${OUTFILE} with error $ERROR\r"  >> pp.log
   exit $ERROR
fi

# Cleanup
echo "Completed transcode! Cleaning up original recording and temp files.\r" >> pp.log
rm -f $VIDEODIR/$INFILE*
cd ..
rm -rf $TEMPDIR/postProcess-$MYPID
cd