#!/bin/sh # convert recording to x264 encoded avi # version 0.7 # consider using myth2mkv instead of this script # usage: # first parameter must be %DIR%/%FILE% of the recording # second parameter must be the desired base name of the output # third parameter must be %CHANID% if you set USECUTLIST=Y # fourth parameter must be %STARTTIME% if you set USECUTLIST=Y # fifth parameter must be %JOBID% for the User Job status to be updated in MythTV # in the mythtv setup screen invoke this script like this: # MYTHTV User Job Command: # /usr/LH/bin/myth2x264 "%DIR%/%FILE%" "%TITLE% - %SUBTITLE%" "%CHANID%" "%STARTTIME%" "%JOBID%" # options: RESOLUTION=960:544 # to keep the source resolution use -1 or to scale down use xxx:xxx (ie 960:544) BITRATE=2500 # use negative bitrate to set output file size in KB (ie. -700000) USECUTLIST=Y # Y or N # where the converted video is stored OUT_DIR=/myth/video # database settings BACKEND_HOSTNAME=${BACKEND_HOSTNAME:-"localhost"} DBUSERNAME=${DBUSERNAME:-"mythtv"} DBPASSWORD=${DBPASSWORD:-"mythtv"} SQLCMD="mysql -u $DBUSERNAME --password=$DBPASSWORD -h $BACKEND_HOSTNAME mythconverg -e" #------FUNCTIONS--------------- update_comment() # Arg_1 = COMMENT { if [ $NO_JOBID = 0 ]; then `$SQLCMD "update jobqueue set comment=\"$1\" where id=\"$JOBID\";"` fi } update_status() # Arg_1 = status code { if [ $NO_JOBID = 0 ]; then `$SQLCMD "update jobqueue set status=\"$1\" where id=\"$JOBID\";"` fi } check_background_progress() # check mencoder progress in background # Arg_1 = PROGRESS CALCULATION { while [ `tail -1 $STATUSFILE | grep -c "^x264 \[info\]: kb/s:"` = 0 ] do sleep 10 check_myth_jobcmds current_status=`tail -1 $STATUSFILE | grep "([ 0-9]\{1,\}%)"` prog_percent=`echo "$current_status" | sed 's_.*(\([ 0-9][ 0-9]\)%).*_\1_'` current_FPS=`echo "$current_status" | sed 's_.*\([ 0-9][ 0-9].[ 0-9][ 0-9]\)fps.*_\1_'` if [ -n "$prog_percent" ]; then prog_percent=`expr $prog_percent / $1` echo "$prog_percent% Completed @ $current_FPS fps" update_comment "$prog_percent% Completed @ $current_FPS fps" fi sleep 10 done } check_myth_jobcmds() # check the myth database for stop pause or resume commands { if [ $NO_JOBID = 0 ]; then CURRENT_CMD=`$SQLCMD "select cmds from jobqueue where id=\"$JOBID\";" | sed '/[0-9]/!d'` case "$CURRENT_CMD" in # JOB_RUN 0) ;; # JOB_PAUSE 1) update_status 6 kill -s STOP $mencoder_pid ;; # JOB_RESUME 2) update_status 4 `$SQLCMD "update jobqueue set cmds=\"0\" where id=\"$JOBID\";"` kill -s CONT $mencoder_pid ;; # JOB_STOP 4) update_status 5 `$SQLCMD "update jobqueue set cmds=\"0\" where id=\"$JOBID\";"` kill -9 $mencoder_pid $command_pid clean_up_files echo "Encode Cancelled" >> $LOGFILE update_status 320 exit ;; esac fi } get_mencoder_pid() { process_name="" i1=1 while [ "$process_name" != "found" ]; do if [ "`ps $mencoder_pid | grep mencoder | sed 's_.*\(mencoder\).*_\1_'`" = "mencoder" ]; then process_name="found" else mencoder_pid=`expr $mencoder_pid + 1` fi i1=`expr $i1 + 1` if [ $i1 -gt 20 ]; then break fi done } clean_up_files() # clean up left over files { unlink $TMPFILE 2> /dev/null unlink $TMPCUTFILE 2> /dev/null unlink $TMPCUTFILE.map 2> /dev/null unlink $TWOPASSFILE 2> /dev/null unlink $TWOPASSFILE.tmp 2> /dev/null unlink $STATUSFILE 2> /dev/null unlink $MENCODER_RETURN_CODE 2> /dev/null unlink $MENCODER_RETURN_CODE_2 2> /dev/null } #-------MAIN SCRIPT------------ # check if %JOBID% is passed from command line JOBID=$5 if [ -z "$JOBID" ]; then NO_JOBID=1 else NO_JOBID=0 fi # create temp filename so multiple instances won't conflict TMPNAME=toX264-$$ TMPFILE=/myth/tmp/$TMPNAME.avi TMPCUTFILE=/myth/tmp/$TMPNAME.mpg MENINPUTFILE=$1 TWOPASSFILE=/myth/tmp/$TMPNAME-2pass.log STATUSFILE=/myth/tmp/$TMPNAME-status.log MENCODER_RETURN_CODE=/myth/tmp/$TMPNAME-mencoder_return_code MENCODER_RETURN_CODE_2=/myth/tmp/$TMPNAME-mencoder_return_code_2 # log file location LOGFILE=/var/log/mythtv/myth2x264.log CDate="`date`" echo "" >> $LOGFILE echo $CDate >> $LOGFILE echo "File to encode: $MENINPUTFILE Name: $2" >> $LOGFILE # start timer beforetime="$(date +%s)" check_myth_jobcmds # check if using cutlist if [ $USECUTLIST = Y ]; then MYTHCOMMFRAMES=`mythutil --getcutlist --chanid "$3" --starttime "$4" | grep 'Cutlist:' | cut -d \ -f 2` if [ -n "$MYTHCOMMFRAMES" ]; then echo "Extracting Cutlist..." >> $LOGFILE update_comment "Extracting Cutlist" /usr/bin/nice -n19 /usr/bin/mythtranscode --chanid "$3" --starttime "$4" --outfile "$TMPCUTFILE" --mpeg2 --honorcutlist MENINPUTFILE=$TMPCUTFILE fi fi # run mencoder in background to do 1st pass conversion echo "Encoding 1st Pass at $RESOLUTION..." >> $LOGFILE ( /usr/bin/nice -n19 /usr/bin/mencoder $MENINPUTFILE -passlogfile $TWOPASSFILE \ -oac copy -ovc x264 -vf lavcdeint,scale=$RESOLUTION \ -x264encopts threads=auto:pass=1:turbo=1:subq=1:frameref=1:bframes=3:bitrate=$BITRATE \ -o /dev/null > $STATUSFILE 2>&1 ; echo $? > $MENCODER_RETURN_CODE ) & mencoder_pid=$! command_pid=$mencoder_pid get_mencoder_pid check_background_progress "2" # run mencoder in background to do 2nd pass conversion echo "Encoding 2nd Pass at $RESOLUTION..." >> $LOGFILE ( /usr/bin/nice -n19 /usr/bin/mencoder $MENINPUTFILE -passlogfile $TWOPASSFILE \ -oac copy -ovc x264 -vf lavcdeint,scale=$RESOLUTION \ -x264encopts threads=auto:pass=2:subq=5:8x8dct:frameref=3:bframes=3:b_pyramid:weight_b:bitrate=$BITRATE \ -o "$TMPFILE" > $STATUSFILE 2>&1 ; echo $? > $MENCODER_RETURN_CODE_2 ) & mencoder_pid=$! command_pid=$mencoder_pid get_mencoder_pid check_background_progress "2 + 50" ERROR=$? # make output filename unique OUTPUTFILE=$OUT_DIR/$2.avi i=1 while [ -e "$OUTPUTFILE" ] do OUTPUTFILE=$OUT_DIR/$2-$i.avi i=`expr $i + 1` done # move temp file to output location chown mythtv "$TMPFILE" && mv "$TMPFILE" "$OUTPUTFILE" # stop timer aftertime="$(date +%s)" seconds="$(expr $aftertime - $beforetime)" if [ $ERROR -eq 0 ]; then echo "File Encoded Successfully: $OUTPUTFILE" >> $LOGFILE hours=$((seconds / 3600)) seconds=$((seconds % 3600)) minutes=$((seconds / 60)) seconds=$((seconds % 60)) echo "Encoding took $hours hour(s) $minutes minute(s) $seconds second(s) @ $current_FPS fps." >> $LOGFILE update_status 272 update_comment "Encode Successful. Encoding Time: $hours hour(s) $minutes minute(s) $seconds second(s)" else update_status 304 update_comment "Encode Failed. Exit status: $ERROR" echo "ERROR: $ERROR" >> $LOGFILE fi clean_up_files