diff options
Diffstat (limited to 'abs/core/linhes-scripts/myth2fuze')
-rwxr-xr-x | abs/core/linhes-scripts/myth2fuze | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/abs/core/linhes-scripts/myth2fuze b/abs/core/linhes-scripts/myth2fuze new file mode 100755 index 0000000..9e8fc3c --- /dev/null +++ b/abs/core/linhes-scripts/myth2fuze @@ -0,0 +1,318 @@ +#!/bin/bash +# convert recording to avi compatable with San Disk Sansa Fuze +# Based on and/or inspired by myth2xvid, the video4fuze project: +# http://code.google.com/p/video4fuze +# and the fuzemux project: +# http://code.google.com/p/fuzemux +# +# version 0.2 +# +# usage: +# first parameter must be %DIR%/%FILE% of the recording +# second parameter must be the %TITLE% for the output filename +# third parameter must be the %SUBTITLE% for the output filename +# fourth parameter must be %CHANID% if you set USECUTLIST=Y +# fifth parameter must be %STARTTIME% for USECUTLIST=Y and output filename +# sixth 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/myth2fuze "%DIR%/%FILE%" "%TITLE%" "%SUBTITLE%" "%CHANID%" "%STARTTIME%" "%JOBID%" + +# options: +USECUTLIST=Y # Y or N + +# check prerequesites +for APP in {fuzemux,mencoder,ffmpeg,mythcommflag,mythtranscode,mysql}; do + /usr/bin/which ${APP} &>/dev/null + ERROR=$? + if [ $ERROR -ne 0 ]; then + echo "${APP} not found in your PATH! Aborting! ERROR: ${ERROR}" >> ${LOGFILE} + update_status 304 + update_comment "${APP} not found in your PATH! Aborting! Exit status: ${ERROR}" + exit 1 + fi +done + +# where the converted video is stored +OUT_DIR=/myth/video/fuze + +# Ensure output directory exists +if [ ! -d ${OUT_DIR} ] ; then + mkdir -p -m777 ${OUT_DIR} +fi + +# database settings +BACKEND_HOSTNAME=${BACKEND_HOSTNAME:-"localhost"} +DBUSERNAME=${DBUSERNAME:-"mythtv"} +DBPASSWORD=${DBPASSWORD:-"mythtv"} +SQLCMD="mysql -u ${DBUSERNAME} --password=${DBPASSWORD} -h ${BACKEND_HOSTNAME} mythconverg -e" + +# create temp filename so multiple instances won't conflict +TMPNAME=toFUZE-$$ +TMPDIR=/myth/tmp +TMPFILE=${TMPDIR}/${TMPNAME}.avi +TMPCUTFILE=${TMPDIR}/${TMPNAME}.mpg +MENINPUTFILE=${1} +TWOPASSFILE=/tmp/${TMPNAME}-2pass.log +STATUSFILE=/tmp/${TMPNAME}-status.log +MENCODER_RETURN_CODE=/tmp/${TMPNAME}-mencoder_return_code +MENCODER_RETURN_CODE_2=/tmp/${TMPNAME}-mencoder_return_code_2 + +# Ensure temp directory exists +if [ ! -d ${TMPDIR} ] ; then + mkdir -p -m777 ${TMPDIR} +fi + +#------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 -cE "^Audio stream:|^Video stream:"` = 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 +} + +run_fuzemux() +# Remux avi to fuze compatable avi +{ +/usr/bin/nice -n19 /usr/bin/fuzemux ${TMPFILE} ${OUTPUTFILE} >> ${LOGFILE} || return 1 +} + +create_thumbnail() +# Create a thumbnail image for the fuze +{ +/usr/bin/nice -n19 /usr/bin/ffmpeg -y -v -1 -i ${OUTPUTFILE} -t 1 -ss 3 \ +-s 224x176 -f image2 ${OUTPUTFILE%.*}.thm >> ${LOGFILE} +} + +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=${6} +if [ -z ${JOBID} ]; then + NO_JOBID=1 +else + NO_JOBID=0 +fi + +# log file location +LOGFILE=/var/log/mythtv/myth2fuze.log +CDate="`date`" +echo "" >> ${LOGFILE} +echo ${CDate} >> ${LOGFILE} +echo "File to encode: ${MENINPUTFILE} Name: ${2} - ${3}" >> ${LOGFILE} + +# start timer +beforetime="$(date +%s)" + +check_myth_jobcmds + +# check if using cutlist +if [ ${USECUTLIST} = Y ]; then + MYTHCOMMFRAMES=$( mythcommflag --getcutlist -f ${MENINPUTFILE} | 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 ${4} --starttime ${5} --outfile ${TMPCUTFILE} --mpeg2 --honorcutlist + MENINPUTFILE=${TMPCUTFILE} + fi +fi + +# run mencoder in background to do 1st pass conversion +echo "Encoding 1st Pass for the Fuze..." >> ${LOGFILE} +( /usr/bin/nice -n19 /usr/bin/mencoder ${MENINPUTFILE} -passlogfile \ +${TWOPASSFILE} -ffourcc DX50 -ofps 20 \ +-vf pp=li,expand=:::::224/176,scale=224:176,harddup -ovc lavc \ +-lavcopts vcodec=mpeg4:vbitrate=683:vmax_b_frames=0:keyint=15:turbo:vpass=1 \ +-nosound -o /dev/null > ${STATUSFILE} 2>&1 ; echo $? > \ +${MENCODER_RETURN_CODE} ) & +mencoder_pid=$! +command_pid=${mencoder_pid} +get_mencoder_pid + +check_background_progress "2" + +if [ `cat ${MENCODER_RETURN_CODE}` -ne 0 ]; then + echo "Mencoder pass #1 exited with error ${MENCODER_RETURN_CODE}. Encoding failed!" + update_status 304 + update_comment "ERROR: Mencoder pass #1 exited with error ${MENCODER_RETURN_CODE}" + clean_up_files + exit 1 +fi + +# run mencoder in background to do 2nd pass conversion +echo "Encoding 2nd Pass for the Fuze..." >> ${LOGFILE} +( /usr/bin/nice -n19 /usr/bin/mencoder ${MENINPUTFILE} -passlogfile \ +${TWOPASSFILE} -ffourcc DX50 -ofps 20 \ +-vf pp=li,expand=:::::224/176,scale=224:176,harddup -ovc lavc \ +-lavcopts vcodec=mpeg4:vbitrate=683:vmax_b_frames=0:keyint=15:vpass=2 \ +-srate 44100 -af resample=44100:0:1,format=s16le -oac mp3lame \ +-lameopts cbr:br=128 -o ${TMPFILE} > ${STATUSFILE} 2>&1 ; echo $? \ +> ${MENCODER_RETURN_CODE_2} ) & +mencoder_pid=$! +command_pid=${mencoder_pid} +get_mencoder_pid + +check_background_progress "2 + 50" + +if [ `cat ${MENCODER_RETURN_CODE_2}` -ne 0 ]; then + echo "Mencoder pass #1 exited with error ${MENCODER_RETURN_CODE}. Encoding failed!" + update_status 304 + update_comment "ERROR: Mencoder pass #1 exited with error ${MENCODER_RETURN_CODE_2}" + clean_up_files + exit 1 +fi + +# make output filename unique, remove punctuation and "special" characters, +# replace spaces with underscores and force lowercase names +OAD=$( echo ${5} | cut -b 1-8 ) +FILENAME=$( echo "${2} ${OAD} ${3}" | tr -d '[:punct:]' \ + | tr -s '[:blank:]' '[_]' | tr '[:upper:]' '[:lower:]' )_fuze.avi + +OUTPUTFILE=${OUT_DIR}/${FILENAME} +ERROR=$? + +if [ ${ERROR} -ne 0 ]; then + echo "Setting output file name exited with error ${ERROR}" >> ${LOGFILE} + update_status 304 + update_comment "ERROR: Setting output file name exited with error ${ERROR} Job failed!" + clean_up_files + exit 1 +fi + +run_fuzemux +ERROR=$? + +if [ ${ERROR} -ne 0 ]; then + echo "Fuzemux exited with error ${ERROR}" >> ${LOGFILE} + update_status 304 + update_comment "ERROR: Fuzemux exited with error ${ERROR} Job Failed!" + clean_up_files + exit 1 +fi + +# ensure mythtv owns the final avi +chown mythtv ${OUTPUTFILE} +ERROR=$? + +if [ ${ERROR} -ne 0 ]; then + echo "Changing ownership of avi to mythtv exited with error ${ERROR}" + update_status 304 + update_comment "ERROR: Changing ownership of avi to mythtv exited with error ${ERROR} Job failed!" + clean_up_files + exit 1 +fi + +create_thumbnail + +# ensure mythtv owns the thumbnail +chown mythtv ${OUTPUTFILE%.*}.thm +ERROR=$? + +if [ ${ERROR} -ne 0 ]; then + echo "Changing ownership of thumbnail to mythtv exited with error ${ERROR}" + update_status 304 + update_comment "ERROR: Changing ownership of thumbnail to mythtv exited with error ${ERROR} Job failed!" + clean_up_files + exit 1 +fi + +# stop timer +aftertime="$(date +%s)" +seconds="$(expr $aftertime - $beforetime)" + 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)" + +clean_up_files |