summaryrefslogtreecommitdiffstats
path: root/abs/core/linhes-scripts/myth2mkv
diff options
context:
space:
mode:
authorMichael Hanson <mihanson@linhes.org>2012-07-10 21:12:52 (GMT)
committerMichael Hanson <mihanson@linhes.org>2012-07-10 21:12:52 (GMT)
commit858b19d7635e8228315daa2f2808b28f80fac67b (patch)
tree3193cba401568d4a9bec5d1e9bc63cddd037bb74 /abs/core/linhes-scripts/myth2mkv
parentba751f7f49901e11050a4d5019fd61157e8d2334 (diff)
downloadlinhes_pkgbuild-858b19d7635e8228315daa2f2808b28f80fac67b.zip
linhes_pkgbuild-858b19d7635e8228315daa2f2808b28f80fac67b.tar.gz
linhes_pkgbuild-858b19d7635e8228315daa2f2808b28f80fac67b.tar.bz2
linhes-scripts: Add myth2mkv to convert recordings to x264/mkv.
Diffstat (limited to 'abs/core/linhes-scripts/myth2mkv')
-rw-r--r--abs/core/linhes-scripts/myth2mkv425
1 files changed, 425 insertions, 0 deletions
diff --git a/abs/core/linhes-scripts/myth2mkv b/abs/core/linhes-scripts/myth2mkv
new file mode 100644
index 0000000..5035748
--- /dev/null
+++ b/abs/core/linhes-scripts/myth2mkv
@@ -0,0 +1,425 @@
+#!/bin/bash
+#
+# Convert video to AVC-1 / h264
+#
+# version 0.25-001
+#
+# Prerequisites:
+# - mythtv >= 0.25
+# - handbrake-cli
+# - mplayer
+# - mkvtoolnix
+#
+# Arguments
+# $1 must be the directory/file of the recording
+# $2 must be chanid
+# $3 must be starttime
+# $4 must be title
+# $5 must be subtitle
+# $6 must be jobid
+# $7 must be quality of encode
+#
+# As a MythTV user job:
+# myth2mkv "%DIR%/%FILE%" "%CHANID%" "%STARTTIME%" "%TITLE%" "%SUBTITLE%" "%JOBID%" HQ|MQ|LQ
+
+########################
+# #
+# Adjustable variables #
+# #
+########################
+
+OUTDIR=/myth/video
+LOGPATH=/var/log/mythtv
+LOGFILE=${LOGPATH}/myth2mkv-$$.log
+
+# TMPDIR is for large transient files
+TMPDIR=/myth/tmp
+
+# x264 tuning:
+# Tune x264 based on content. Valid options for TUNING are:
+# film, animation, grain, stillimage, psnr, ssim, fastdecode, zerolatency
+# Separate multiple options with a comma. DEFAULT: none
+TUNING=""
+
+# Custom cropping. Useful if you have a 4:3 image in a HD frame or if
+# HandBrake's autocrop smarts fail you.
+# Crop 240 pixels off the left and right for 4:3 image in 1920x1080 frame
+# Crop 160 pixels off the left and right for 4:3 image in 1280x720 frame
+# <T:B:L:R>
+# i.e. 0:0:240:240
+# Default: In HQ: CROP="0:0:0:0" (no cropping).
+# IN MQ and LQ: autocrop.
+CROP=""
+
+# Force custom output resolution.
+# Default: Keep same resolution as input file (less any cropping).
+WIDTH=""
+HEIGHT=""
+
+# Force use/non-use of deinterlacing filter. Y|N|G (Yes, No, Guess)
+# Default: G - Guess based on source resolution.
+# If the source video width is 1920, 1440, 852, 704, 640 or 528 pixels
+# "G" will deinterlace the video. Change to "Y" to force use of deinterlacing
+# filter or to "N" to NOT use deinterlace filter no matter the resolution.
+DEINT="G"
+
+############################
+# #
+# End adjustable variables #
+# #
+############################
+
+if [[ -e $HOME/.mythtv/mysql.txt ]] ; then
+ . $HOME/.mythtv/mysql.txt
+else
+ DBHostName=${DBHostName:-"localhost"}
+ DBUserName=${DBUserName:-"mythtv"}
+ DBPassword=${DBPassword:-"mythtv"}
+ DBName=${DBName:-"mythconverg"}
+fi
+
+if [[ ! -d ${TMPDIR} ]] ; then
+ mkdir -p ${TMPDIR}
+fi
+
+if [[ ! -d ${OUTDIR} ]] ; then
+ mkdir -p ${OUTDIR}
+fi
+
+#------FUNCTIONS---------------
+update_comment()
+# Arg_1 = COMMENT
+{
+if [ ${NO_JOBID} -eq 0 ]; then
+ SQL_CMD="update jobqueue set comment=\"${1}\" where id=\"${JOBID}\";"
+ `${MYSQLCMD} "${SQL_CMD}"`
+fi
+}
+
+check_background_progress()
+# check handbrake progress in background
+{
+while [ `tail -2 ${STATUSFILE} | grep -c "^HandBrake has exited"` = 0 ]
+do
+ sleep 10
+ check_myth_jobcmds
+ pass=`tail -1 ${STATUSFILE} | egrep -o -e 'task [0-9]' | tail -1 | sed 's/task\ //g'`
+ prog_percent=`tail -1 ${STATUSFILE} | egrep -o -e '[0-9]*\.[0-9]. %' | tail -1 | sed 's/\ %//g'`
+ current_FPS=`tail -1 ${STATUSFILE} | egrep -o -e 'avg [0-9.]*\.[0-9]* fps' | tail -1 | sed -e 's/avg\ //g' -e 's/\ fps//g'`
+ current_ETA=`tail -1 ${STATUSFILE} | egrep -o -e 'ETA [0-9.][0-9.]h[0-9.][0-9.]m[0-9.][0-9.]s' | tail -1`
+ if [ -n "$prog_percent" ]; then
+ echo "Pass ${pass}, ${prog_percent}% @ ${current_FPS} fps. ${current_ETA}"
+ update_comment "Pass ${pass} of 2, ${prog_percent}% @ ${current_FPS} fps. ${current_ETA}"
+ fi
+ sleep 10
+done
+}
+
+check_myth_jobcmds()
+# check the myth database for stop pause or resume commands
+{
+if [[ ${NO_JOBID} -eq 0 ]] ; then
+ CURRENT_CMD=`${MYSQLCMD} "select cmds from jobqueue where id = \"${JOBID}\";"`
+ case "${CURRENT_CMD}" in
+ # JOB_RUN
+ 0) ;;
+ # JOB_PAUSE
+ 1) `${MYSQLCMD} "update jobqueue set status=\"6\" where id=\"${JOBID}\";"`
+ kill -s STOP ${handbrake_pid} ;;
+ # JOB_RESUME
+ 2) `${MYSQLCMD} "update jobqueue set status=\"4\" where id=\"${JOBID}\";"`
+ `${MYSQLCMD} "update jobqueue set cmds=\"0\" where id=\"${JOBID}\";"`
+ kill -s CONT ${handbrake_pid} ;;
+ # JOB_STOP
+ 4) `${MYSQLCMD} "update jobqueue set status=\"5\" where id=\"${JOBID}\";"`
+ `${MYSQLCMD} "update jobqueue set cmds=\"0\" where id=\"${JOBID}\";"`
+ kill -9 ${handbrake_pid} ${command_pid}
+ clean_up_files
+ echo "Encode Cancelled" >> ${LOGFILE}
+ `${MYSQLCMD} "update jobqueue set status=\"320\" where id=\"${JOBID}\";"`
+ exit ;;
+ esac
+fi
+}
+
+get_info_for_hb() {
+# Collect some info about source file
+
+/usr/bin/mplayer -nolirc -identify -frames 0 "${HBINPUTFILE}" \
+ 2>/dev/null 1>"${IDFILE}"
+
+VIDEOW=$( grep ID_VIDEO_WIDTH= "${IDFILE}" | awk -F= '{ print $NF }' )
+FPS=$( grep ID_VIDEO_FPS= "${IDFILE}" | awk -F= '{ print $NF }' )
+
+# HandBrake does not like a framerate of 29.970, so let's drop the 0
+if [[ ${FPS} = "29.970" ]] ; then
+ FPS="29.97"
+fi
+
+# A rough guestimation that if the video width is 1920, 1440, 852, 704, 640 or
+# 528 pixels it is probably interlaced.
+if [[ ${DEINT} = Y ]] ; then
+ DEINT="-d slow"
+else
+ if [[ ${DEINT} = N ]] ; then
+ DEINT=""
+ else
+ if [[ ${VIDEOW} = 1920 || ${VIDEOW} = 1440 || ${VIDEOW} = 852 || \
+ ${VIDEOW} = 704 || ${VIDEOW} = 640 || ${VIDEOW} = 528 ]] ; then
+ DEINT="-d slow"
+ else
+ DEINT=""
+ fi
+ fi
+fi
+
+if [[ -n ${DEINT} ]] ; then
+ if [[ ${QUALITY} = LQ ]] ; then
+ DEINT="-d fast"
+ fi
+fi
+
+if [[ -n ${TUNING} ]] ; then
+ TUNING="--x264-tune ${TUNING}"
+fi
+
+if [[ -n ${CROP} ]] ; then
+ CROP="--crop ${CROP}"
+fi
+
+if [[ -n ${WIDTH} ]] ; then
+ WIDTH="-w ${WIDTH} -X ${WIDTH}"
+fi
+
+if [[ -n ${HEIGHT} ]] ; then
+ HEIGHT="-l ${HEIGHT} -Y ${HEIGHT}"
+fi
+
+if [[ ${QUALITY} = HQ ]] ; then
+ if [[ -n ${CROP} ]] ; then
+ CROP="--crop ${CROP}"
+ else
+ CROP="--crop 0:0:0:0"
+ fi
+ HB_OPTS="-o ${TMPFILE} -f mkv -m -e x264 ${TUNING} -x b-adapt=2:rc-lookahead=50 -b 5000 -2 -T ${WIDTH} ${HEIGHT} -r ${FPS} --cfr ${CROP} ${DEINT} -a 1 -E copy -s 1"
+else
+ if [[ ${QUALITY} = LQ ]] ; then
+ HB_OPTS="-o ${TMPFILE} -f mkv -m -e x264 ${TUNING} -b 1250 ${WIDTH} ${HEIGHT} -r ${FPS} --pfr ${CROP} ${DEINT} -a 1 -E lame -B 128 -Q 8 -6 stereo -s 1"
+ else
+ # Fallback to "MQ"
+ HB_OPTS="-o ${TMPFILE} -f mkv -m -e x264 ${TUNING} -b 2500 -2 -T ${WIDTH} ${HEIGHT} -r ${FPS} --pfr ${CROP} ${DEINT} -a 1 -E lame -B 256 -Q 3 -6 stereo -s 1"
+ fi
+fi
+}
+
+get_handbrake_pid()
+{
+process_name=""
+i1=1
+while [ "${process_name}" != "found" ]; do
+ handbrake_pid=`expr ${handbrake_pid} + 1`
+ i1=`expr ${i1} + 1`
+ if [ "`ps ${handbrake_pid} | grep HandBrakeCLI | sed 's_.*\(HandBrakeCLI\).*_\1_'`" = "HandBrakeCLI" ]; then
+ process_name="found"
+ fi
+ if [ ${i1} -gt 20 ]; then
+ break
+ fi
+done
+}
+
+tag_file() {
+DATE=`date`
+
+# Create a tag file here
+echo "<?xml version='1.0' encoding='ISO-8859-1'?>" > "${TAG_FILE}"
+echo "" >> "${TAG_FILE}"
+echo "<!DOCTYPE Tags SYSTEM 'matroskatags.dtd'>" >> "${TAG_FILE}"
+echo "" >> "${TAG_FILE}"
+echo "<Tags>" >> "${TAG_FILE}"
+echo " <Tag>" >> "${TAG_FILE}"
+echo " <Simple>" >> "${TAG_FILE}"
+echo " <Name>TITLE</Name>" >> "${TAG_FILE}"
+echo " <String>${TITLE}</String>" >> "${TAG_FILE}"
+echo " <Simple>" >> "${TAG_FILE}"
+echo " <Name>SUBTITLE</Name>" >> "${TAG_FILE}"
+echo " <String>${SUBTITLE}</String>" >> "${TAG_FILE}"
+echo " <Simple>" >> "${TAG_FILE}"
+echo " <Name>SUMMARY</Name>" >> "${TAG_FILE}"
+echo " <String>${DESCR}</String>" >> "${TAG_FILE}"
+echo " </Simple>" >> "${TAG_FILE}"
+echo " <Simple>" >> "${TAG_FILE}"
+echo " <Name>DATE_RELEASED</Name>" >> "${TAG_FILE}"
+echo " <String>${OAD}</String>" >> "${TAG_FILE}"
+echo " </Simple>" >> "${TAG_FILE}"
+echo " </Simple>" >> "${TAG_FILE}"
+echo " </Simple>" >> "${TAG_FILE}"
+echo " <Simple>" >> "${TAG_FILE}"
+echo " <Name>ENCODER</Name>" >> "${TAG_FILE}"
+echo " <String>HandBrakeCLI ${HBCLIVER}</String>" >> "${TAG_FILE}"
+echo " </Simple>" >> "${TAG_FILE}"
+echo " <Simple>" >> "${TAG_FILE}"
+echo " <Name>DATE_TAGGED</Name>" >> "${TAG_FILE}"
+echo " <String>${DATE}</String>" >> "${TAG_FILE}"
+echo " </Simple>" >> "${TAG_FILE}"
+echo " </Tag>" >> "${TAG_FILE}"
+echo "</Tags>" >> "${TAG_FILE}"
+
+# Add tag info into MKV file
+echo "Adding tag info to ${TITLE} - ${SUBTITLE} ..." >> ${LOGFILE}
+
+/usr/bin/mkvpropedit -r ${LOGFILE} -t all:"${TAG_FILE}" "${TMPFILE}"
+}
+
+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 ${STATUSFILE} 2> /dev/null
+unlink ${IDFILE} 2> /dev/null
+unlink ${HB_RETURN_CODE} 2> /dev/null
+unlink ${TAG_FILE} 2> /dev/null
+}
+
+#-------MAIN SCRIPT------------
+
+# create temp filename so multiple instances won't conflict
+TMPNAME=toX264-$$
+TMPFILE=${TMPDIR}/${TMPNAME}.mkv
+TMPCUTFILE=${TMPDIR}/${TMPNAME}.mpg
+HBINPUTFILE="${1}"
+TITLE="${4}"
+SUBTITLE="${5}"
+JOBID="${6}"
+QUALITY="${7}"
+BASE=`basename ${HBINPUTFILE}`
+HBCLIVER=`pacman -Q | grep handbrake-cli | awk '{ print $NF }' | awk -F"-" '{ print $1 }'`
+STATUSFILE=/tmp/${TMPNAME}-status.log
+HB_RETURN_CODE=/tmp/${TMPNAME}-hb_return_code
+IDFILE=/tmp/${TMPNAME}-id.txt
+TAG_FILE=/tmp/${TMPNAME}.xml
+MYSQLCMD="mysql -B --skip-column-names -u ${DBUserName} -p${DBPassword} -h ${DBHostName} -D ${DBName} -e"
+OAD=`${MYSQLCMD} "select originalairdate from recorded where basename LIKE '${BASE}';"`
+DESCR=`${MYSQLCMD} "select description from recorded where basename LIKE '${BASE}';" | sed 's/\&/and/g'`
+USER=`whoami`
+
+# check if %JOBID% is passed from command line
+if [ -z ${JOBID} ]; then
+ NO_JOBID=1
+else
+ NO_JOBID=0
+fi
+
+# log file location
+CDate="`date`"
+echo "" >> ${LOGFILE}
+echo $CDate >> ${LOGFILE}
+echo "File to encode: ${HBINPUTFILE}" >> ${LOGFILE}
+echo " --> Name: ${TITLE} - ${SUBTITLE}" >> ${LOGFILE}
+echo " --> Temporary Files: ${TMPNAME}.*" >> ${LOGFILE}
+echo "" >> ${LOGFILE}
+
+get_info_for_hb
+ERROR=$?
+
+if [[ ${ERROR} != 0 ]] ; then
+ echo "Error parsing source file information!" >> ${LOGFILE}
+ cat ${IDFILE} >> ${LOGFILE}
+ clean_up_files
+ exit 1
+fi
+
+# start timer
+beforetime="$(date +%s)"
+
+check_myth_jobcmds
+
+# If there is a cutlist, use it:
+if [[ -n `mythutil --getcutlist --chanid "${2}" --starttime "${3}" | grep \
+ Cutlist: | awk -F": " '{ print $NF }'` ]] ; then
+ echo "Applying cutlist for ${TITLE} - ${SUBTITLE} ..." >> ${LOGFILE}
+ mythtranscode --chanid "${2}" --starttime "${3}" -m --honorcutlist \
+ -q --loglevel info --logpath "${LOGPATH}" -o "${TMPCUTFILE}"
+ mythtrans_pid=$!
+ ERROR=$?
+ HBINPUTFILE=${TMPCUTFILE}
+fi
+
+if [[ ${ERROR} != 0 ]] ; then
+ echo "MythTranscode error!" >> ${LOGFILE}
+ echo "Check ${LOGPATH}/mythtranscode.date.${mythtrans_pid}.log for mythtranscode error" >> ${LOGFILE}
+ clean_up_files
+ exit 1
+fi
+
+# run handbrake in background to do conversion
+echo "Encoding ${TITLE} - ${SUBTITLE} ..." >> ${LOGFILE}
+
+( /usr/bin/nice -n19 nohup /usr/bin/HandBrakeCLI -i ${HBINPUTFILE} ${HB_OPTS} \
+ > ${STATUSFILE} 2>&1 ; echo $? > ${HB_RETURN_CODE} ) &
+handbrake_pid=$!
+command_pid=${handbrake_pid}
+get_handbrake_pid
+
+check_background_progress
+
+if [[ `cat ${HB_RETURN_CODE}` != 0 ]] ; then
+ echo "HandBrakeCLI error!" >> ${LOGFILE}
+ cat ${STATUSFILE} >> ${LOGFILE}
+ clean_up_files
+ exit 1
+fi
+
+tag_file
+ERROR=$?
+
+if [[ ${ERROR} != 0 ]] ; then
+ echo "Error creating tag file!" >> ${LOGFILE}
+ cat ${TAG_FILE} >> ${LOGFILE}
+ clean_up_files
+ exit 1
+fi
+
+# make output filename unique and do not clobber an existing file
+# Build a final file name
+FILE=$( echo "${TITLE,,} ${OAD} ${SUBTITLE,,}" | tr -d [:punct:] | tr [:blank:] "_" | tr -s "_" )
+OUTPUTFILE="${OUTDIR}/${FILE}.mkv"
+i=1
+while [ -e "${OUTPUTFILE}" ]
+do
+ OUTPUTFILE="${OUTDIR}/${FILE}-${i}.mkv"
+ i=`expr $i + 1`
+done
+
+# move temp file to output location
+chown -v "${USER}" "${TMPFILE}" >> ${LOGFILE}
+mv -v "${TMPFILE}" "$OUTPUTFILE" >> ${LOGFILE}
+ERROR=$?
+
+if [[ ${ERROR} != 0 ]] ; then
+ echo "Error moving ${TMPFILE} to ${OUTPUTFILE} !" >> ${LOGFILE}
+ clean_up_files
+ exit 1
+fi
+
+# 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}
+ `${MYSQLCMD} "update jobqueue set status = \"272\" where id = \"${JOBID}\";"`
+ update_comment "Encode Successful. Encoding Time: ${hours} hour\(s\) ${minutes} minute\(s\) ${seconds} second\(s\)"
+else
+ echo "ERROR: ${ERROR}" >> ${LOGFILE}
+fi
+
+# Clean up
+clean_up_files