Difference between revisions of "Mythbrake"
(Add cat) |
Ares Drake (talk | contribs) m (typo fix) |
||
(8 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
This script shall be called as MythTV [[User Jobs|user job]]. It transcodes the DVB recordings (mpeg files) using [http://handbrake.fr Handbrake]. | This script shall be called as MythTV [[User Jobs|user job]]. It transcodes the DVB recordings (mpeg files) using [http://handbrake.fr Handbrake]. | ||
− | =Features= | + | =Overview= |
− | *On a Phenom II X4 2,8Ghz it is a lot faster than mythnuv2mkv using comparable quality settings. With Mythbrake I get ~40fps for HDTV and around ~250fps on SDTV without noticable quality degradation compared to the source file. | + | ==Features== |
− | * All transcodings are single pass with [https://trac.handbrake.fr/wiki/ConstantQuality constant quality] as this results in the same quality as dual pass without the need for a second pass | + | *On a Phenom II X4 2,8Ghz it is a lot faster than mythnuv2mkv using comparable quality settings. With Mythbrake I get ~40fps for 720p HDTV and around ~250fps on SDTV without noticable quality degradation compared to the source file. |
+ | *One reason for the speed is that Mythbrake can preserve [https://trac.handbrake.fr/wiki/AnamorphicGuide anamorphic pixels], thus saving on resizing. mythnuv2mkv insists on resizing to square pixels, increasing file size and encoding time. | ||
+ | * All transcodings are single pass with [https://trac.handbrake.fr/wiki/ConstantQuality constant quality] as this results in the same quality as with dual pass but without the need for a second pass. This further increases the speed adavantage. The only downside compared to dual pass is a slightly less predictable file size. As burning files to optical media (with a fixed size) is imho a thing of the past, exact file size hardly matters though. | ||
* Can transcode using mutiple languages (up to 3) | * Can transcode using mutiple languages (up to 3) | ||
* Preserves surround sound (e.g. AC3 5.1) | * Preserves surround sound (e.g. AC3 5.1) | ||
* Alerts via email in case of an error, so no problems lurk in the dark until the recording sheduled for transcoding is overwritten with newer recordings. | * Alerts via email in case of an error, so no problems lurk in the dark until the recording sheduled for transcoding is overwritten with newer recordings. | ||
+ | ==Notes== | ||
+ | *I have no programming education and my job has nothing to do with computing. I wrote this script from what I learned from google and reading man pages. It is wirtten primarily for my own purposes to extend the lovely mythtv. It may not match your needs, but perhaps someone else's. This script may contain bugs, do things in suboptimal ways or eat your cat, be prepared and careful. | ||
+ | *Because of the above, the script is written in bash. This is suboptimal in some ways (e.g. answering the question wether a channel has commercials) but on the other hand has little requirements and might be easier to understand to new users. | ||
+ | *This script is tested on RHEL6 (Sientific Linux) with MythTV Ver. 0.25 and 0.26 from the atrpms repository. | ||
+ | *If you find any bugs or problems feel free to mail me at ares.drake@gmail.com | ||
− | = | + | ==Requirements== |
− | + | *[http://handbrake.fr Handbrake] is used for the transcoding and needs to be installed on your machine. See the handbrake website for installation details. | |
+ | *[http://mediainfo.sourceforge.net/ Mediainfo] is used for probing the source file (i.e. the recording) what audio tracks are available and wether the recoding is HDTV. Download on their website. | ||
+ | ==Source Formats== | ||
'''HDTV''' will be reencoded with Mpeg4 AVC H264 to save space. All HDTV channels I can receive here in Germany are without commercials, so I don't bother running mythcommflag on them. In case your situation differs you'll have to modify the script. | '''HDTV''' will be reencoded with Mpeg4 AVC H264 to save space. All HDTV channels I can receive here in Germany are without commercials, so I don't bother running mythcommflag on them. In case your situation differs you'll have to modify the script. | ||
'''SDTV''' will have commercials cut out if necessary and will then be transcoded to Mpeg4 ASP (H263, Xvid, DivX). The scipt will check the ChanID of the recording to decide wethere there are commercials, so you have to adapt the list of ChanIDs to your setup. | '''SDTV''' will have commercials cut out if necessary and will then be transcoded to Mpeg4 ASP (H263, Xvid, DivX). The scipt will check the ChanID of the recording to decide wethere there are commercials, so you have to adapt the list of ChanIDs to your setup. | ||
− | If the ChanID indicates the source file contains commercials, I use Mpeg4 ASP instead of Mpeg4 AVC on SDTV recordings because the transcoding is much faster and it is easier to cut later on as mythcommflag isn't perfect. For manual cutting afterwards I use [http://avidemux.org/ Avidemux]. | + | If the ChanID indicates the source file contains commercials, I use Mpeg4 ASP instead of Mpeg4 AVC on SDTV recordings because the transcoding is much faster and it is easier to cut later on as mythcommflag isn't perfect. For manual cutting afterwards I use [http://avidemux.org/ Avidemux]. If no commercials are present, the SDTV recordings are transcoded to H264 as well. |
'''Audio''': You can pass this script up to three languages and corresponding descriptions. The script will then automatically search the source file for the best track (i.e. the track with the most channels, e.g. 5.1 is better than stereo) for each given language. Surround sound is preserved, tracks with more than 2 channels are passed through without audio transcoding, mono or stereo tracks are transcoded to 128kbits/sec. | '''Audio''': You can pass this script up to three languages and corresponding descriptions. The script will then automatically search the source file for the best track (i.e. the track with the most channels, e.g. 5.1 is better than stereo) for each given language. Surround sound is preserved, tracks with more than 2 channels are passed through without audio transcoding, mono or stereo tracks are transcoded to 128kbits/sec. | ||
− | |||
=Change Logs= | =Change Logs= | ||
+ | ==Version 1.3b== | ||
+ | * 5 November 2012 | ||
+ | * Bugfixes | ||
+ | |||
==Version 1.3== | ==Version 1.3== | ||
* 8 May 2012 | * 8 May 2012 | ||
Line 38: | Line 50: | ||
=Scripts= | =Scripts= | ||
− | ==Version 1. | + | Note: For MythTV versions 0.25 and older, "%STARTTIMEUTC%" needs to be changed to "%STARTTIME%" |
+ | ==Version 1.3b== | ||
<pre> | <pre> | ||
#!/bin/bash | #!/bin/bash | ||
− | |||
# Save this as mythbrake.sh and make the file executable | # Save this as mythbrake.sh and make the file executable | ||
# Written by Ares Drake, ares.drake@gmail.com | # Written by Ares Drake, ares.drake@gmail.com | ||
Line 49: | Line 61: | ||
#USAGE:###################### | #USAGE:###################### | ||
# This Sript shall be called as a MythTV user job like as follows: | # This Sript shall be called as a MythTV user job like as follows: | ||
− | # /path/to/mythbrake.sh "%DIR" "%FILE%" "%CHANID%" "% | + | # /path/to/mythbrake.sh "%DIR%" "%FILE%" "%CHANID%" "%STARTTIMEUTC%" "%TITLE%" "%SUBTITLE%" "%CATEGORY%" |
############################# | ############################# | ||
# | # | ||
Line 57: | Line 69: | ||
# mediainfo: http://mediainfo.sourceforge.net/ | # mediainfo: http://mediainfo.sourceforge.net/ | ||
# handbrake with dependencies: http://www.handbrake.fr | # handbrake with dependencies: http://www.handbrake.fr | ||
+ | # Installation of these is convered on their sites | ||
############################# | ############################# | ||
Line 62: | Line 75: | ||
######SOME CONSTANSTS FOR USER EDITING###### | ######SOME CONSTANSTS FOR USER EDITING###### | ||
############################################ | ############################################ | ||
− | logdir="/opt/mythtv/transcodelogs" | + | logdir="/opt/mythtv/transcodelogs" #change to your needs for logs |
errormail="youremail@adress.com" # this email address will be informed in case of errors | errormail="youremail@adress.com" # this email address will be informed in case of errors | ||
outdir="/where/you/want/it" # specify directory where you want the transcoded file to be placed | outdir="/where/you/want/it" # specify directory where you want the transcoded file to be placed | ||
#Audio track (language) selection, your values must match the output syntax of mediainfo | #Audio track (language) selection, your values must match the output syntax of mediainfo | ||
− | # | + | #check "mediainfo --Inform="Audio;%Language/String% yoursourcefile.mpg" in the terminal for syntax |
lang_1="German" #Primary language you want to keep | lang_1="German" #Primary language you want to keep | ||
− | lang_2="qaa" #Secondary language you want to keep, use "none" to skip, | + | lang_2="qaa" #Secondary language you want to keep, use "none" to skip, quaa is original language, wich is English most of the time |
lang_3="French" #Thid language you want to keep, use "none" to skip | lang_3="French" #Thid language you want to keep, use "none" to skip | ||
lang1_name="Deutsch" #This is the label of the 1st audio stream inside the final video file | lang1_name="Deutsch" #This is the label of the 1st audio stream inside the final video file | ||
Line 102: | Line 115: | ||
fi | fi | ||
outfile="$outdir/$filename" | outfile="$outdir/$filename" | ||
− | lang_1_count= | + | let lang_1_count=0 |
− | lang_2_count= | + | let lang_2_count=0 |
− | lang_3_count= | + | let lang_3_count=0 |
lang_1_track="" | lang_1_track="" | ||
lang_2_track="" | lang_2_track="" | ||
Line 122: | Line 135: | ||
then | then | ||
#source file does not exist | #source file does not exist | ||
− | scriptstoptime=$(date +%F-%H | + | scriptstoptime=$(date +%F-%H%M%S) |
echo "Error at $scriptstoptime: Source file not found " >> "$logfile" | echo "Error at $scriptstoptime: Source file not found " >> "$logfile" | ||
echo "Maybe wrong path or missing permissions?" >> "$logfile" | echo "Maybe wrong path or missing permissions?" >> "$logfile" | ||
Line 136: | Line 149: | ||
# There were errors with Mediainfo. | # There were errors with Mediainfo. | ||
then | then | ||
− | scriptstoptime=$(date +%F-%H | + | scriptstoptime=$(date +%F-%H%M%S) |
echo "Error prior to encoding at $scriptstoptime" >> "$logfile" | echo "Error prior to encoding at $scriptstoptime" >> "$logfile" | ||
echo "Mediainfo encountered an error. Maybe mediainfo is not installed, or not in your path" >> "$logfile" | echo "Mediainfo encountered an error. Maybe mediainfo is not installed, or not in your path" >> "$logfile" | ||
Line 146: | Line 159: | ||
echo "Mediainfo Run successful." >> "$logfile" | echo "Mediainfo Run successful." >> "$logfile" | ||
fi | fi | ||
+ | |||
Line 165: | Line 179: | ||
#Finished building arrays | #Finished building arrays | ||
+ | echo "Array built successful, starting looping over audio tracks. There are $acount tracks, so we loop $acount times." >> "$logfile" | ||
for (( I=1; I <= "$acount"; I++ )) | for (( I=1; I <= "$acount"; I++ )) | ||
Line 170: | Line 185: | ||
#loop through all tracks, currently active track is $I | #loop through all tracks, currently active track is $I | ||
#${ARBITR[$I]},${ARLANG[$I]},${ARCHAN[$I]},${ARCODEC[$I]} gives values for track $I | #${ARBITR[$I]},${ARLANG[$I]},${ARCHAN[$I]},${ARCODEC[$I]} gives values for track $I | ||
+ | echo "loop number $I." >> "$logfile" | ||
#select track for first language | #select track for first language | ||
− | + | currentlang=${ARLANG[$I]} | |
+ | if [ "$currentlang" == "$lang_1" ] | ||
then | then | ||
− | $lang_1_count = $lang_1_count+1 | + | echo -n "track $I matching $lang1_name" >> "$logfile" |
− | if [ $lang_1_count | + | let "lang_1_count += 1" #let $lang_1_count = $lang_1_count+1 |
+ | if [ $lang_1_count -eq 1 ] | ||
then | then | ||
#if this is the first track with desired language, we use it. | #if this is the first track with desired language, we use it. | ||
+ | echo " and is the first track matching" >> "$logfile" | ||
lang_1_track=$I | lang_1_track=$I | ||
− | lang_1_chan="${ARCHAN[$I]}" | + | let lang_1_chan="${ARCHAN[$I]}" |
lang_1_codec="${ARCODEC[$I]}" | lang_1_codec="${ARCODEC[$I]}" | ||
− | elif [ ${ARCHAN[$I]} | + | elif [ "${ARCHAN[$I]}" -gt "${ARCHAN[$lang_1_track]}" ] |
then | then | ||
+ | echo " and is better than previous match" >> "$logfile" | ||
#there is already a track with the same desired language but this current track | #there is already a track with the same desired language but this current track | ||
#has more channels, so we use this one instead of the previous track. | #has more channels, so we use this one instead of the previous track. | ||
lang_1_track=$I | lang_1_track=$I | ||
− | lang_1_chan= | + | let lang_1_chan=${ARCHAN[$I]} |
lang_1_codec="${ARCODEC[$I]}" | lang_1_codec="${ARCODEC[$I]}" | ||
fi | fi | ||
fi | fi | ||
+ | echo "Audio track1 iteration succesfull" >> "$logfile" | ||
+ | |||
#select track for second language | #select track for second language | ||
− | if [ "$lang_2" ! | + | if [ "$lang_2" != "none" ] |
then | then | ||
− | if ["$ | + | if [ "$currentlang" == "$lang_2" ] |
− | then | + | then |
− | + | echo -n "track $I matching $lang2_name" >> "$logfile" | |
− | + | let "lang_2_count += 1" | |
− | + | if [ $lang_2_count -eq 1 ] | |
− | + | then | |
− | + | #if this is the first track with desired language, we use it. | |
− | + | echo " and is the first track matching" >> "$logfile" | |
− | + | let lang_2_track=$I | |
− | + | let lang_2_chan="${ARCHAN[$I]}" | |
− | + | lang_2_codec="${ARCODEC[$I]}" | |
− | + | elif [ "${ARCHAN[$I]}" -gt "${ARCHAN[$lang_2_track]}" ] | |
− | + | then | |
− | + | echo " and is better than previous match" >> "$logfile" | |
− | + | #there is already a track with the same desired language but this current track | |
− | + | #has more channels, so we use this one instead of the previous track. | |
− | + | let lang_2_track=$I | |
+ | let lang_2_chan=${ARCHAN[$I]} | ||
+ | lang_2_codec="${ARCODEC[$I]}" | ||
+ | fi | ||
fi | fi | ||
fi | fi | ||
+ | echo "Audio track2 iteration succesfull" >> "$logfile" | ||
+ | |||
− | if [ "$lang_3" ! | + | if [ "$lang_3" != "none" ] |
then | then | ||
#select track for third language | #select track for third language | ||
− | if ["$ | + | if [ "$currentlang" == "$lang_3" ] |
then | then | ||
− | $ | + | echo -n "track $I matching $lang3_name" >> "$logfile" |
− | if [ $lang_3_count | + | let "lang_3_count += 1" |
+ | if [ $lang_3_count -eq 1 ] | ||
then | then | ||
#if this is the first track with desired language, we use it. | #if this is the first track with desired language, we use it. | ||
− | lang_3_track=$I | + | echo " and is the first track matching" >> "$logfile" |
− | lang_3_chan="${ARCHAN[$I]}" | + | let lang_3_track=$I |
+ | let lang_3_chan="${ARCHAN[$I]}" | ||
lang_3_codec="${ARCODEC[$I]}" | lang_3_codec="${ARCODEC[$I]}" | ||
− | elif [ | + | elif [ "${ARCHAN[$I]}" -gt "${ARCHAN[$lang_3_track]}" ] |
then | then | ||
+ | echo " and is better than previous match" >> "$logfile" | ||
#there is already a track with the same desired language but this current track | #there is already a track with the same desired language but this current track | ||
#has more channels, so we use this one instead of the previous track. | #has more channels, so we use this one instead of the previous track. | ||
− | lang_3_track=$I | + | let lang_3_track=$I |
− | lang_3_chan="${ARCHAN[$I]}" | + | let lang_3_chan="${ARCHAN[$I]}" |
lang_3_codec="${ARCODEC[$I]}" | lang_3_codec="${ARCODEC[$I]}" | ||
fi | fi | ||
Line 237: | Line 267: | ||
fi | fi | ||
fi | fi | ||
+ | echo "Audio track3 iteration succesfull" >> "$logfile" | ||
done | done | ||
+ | echo "Audio track iteration succesfull" >> "$logfile" | ||
#okay, how may tracks to include in the outfile now? | #okay, how may tracks to include in the outfile now? | ||
− | + | let totallangcount=($lang_1_count + $lang_2_count + $lang_3_count) | |
+ | if [ $totallangcount -eq 0 ] | ||
# No suitable audio track found. | # No suitable audio track found. | ||
then | then | ||
− | scriptstoptime=$(date +%F-%H | + | scriptstoptime=$(date +%F-%H%M%S) |
echo "Audio track error at $scriptstoptime" >> "$logfile" | echo "Audio track error at $scriptstoptime" >> "$logfile" | ||
echo "The script was unable to find a matching audio track, aborting." >> "$logfile" | echo "The script was unable to find a matching audio track, aborting." >> "$logfile" | ||
Line 253: | Line 286: | ||
fi | fi | ||
− | if | + | |
+ | |||
+ | echo "Total number of tracks selected: $totallangcount" >> "$logfile" | ||
+ | |||
+ | |||
+ | ###Now generate Handbrake commands from the above#### | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | if [ $lang_1_count -ge 1 ] | ||
then | then | ||
echo "Selected track $lang_1_track for $lang_1" >> "$logfile" | echo "Selected track $lang_1_track for $lang_1" >> "$logfile" | ||
− | audiotacks="$ | + | audiotacks="$lang_1_track" #Handbrake_CLI -a |
− | if | + | if [ $lang_1_chan -gt 2 ] |
# more than 2 channels present, pass through track without transcoding,perfect quality | # more than 2 channels present, pass through track without transcoding,perfect quality | ||
then | then | ||
Line 271: | Line 315: | ||
fi | fi | ||
else | else | ||
− | echo "No track found for $lang_1" >> "$logfile" | + | echo "No track found for $lang_1 = $lang1_name" >> "$logfile" |
fi | fi | ||
− | if | + | if [ $lang_2_count -ge 1 ] |
then | then | ||
echo "Selected track $lang_2_track for $lang_2" >> "$logfile" | echo "Selected track $lang_2_track for $lang_2" >> "$logfile" | ||
− | if $audiotacks | + | if [ -z "$audiotacks" ] |
#no track for first language present | #no track for first language present | ||
then | then | ||
− | audiotacks="$ | + | audiotacks="$lang_2_track" #Handbrake_CLI -a |
− | if | + | if [ $lang_2_chan -gt 2 ] |
# more than 2 channels present | # more than 2 channels present | ||
#pass through track without transcoding,perfect quality | #pass through track without transcoding,perfect quality | ||
Line 297: | Line 341: | ||
else | else | ||
#first track present, append | #first track present, append | ||
− | audiotacks="$audiotracks,$ | + | audiotacks="$audiotracks,$lang_2_track" #Handbrake_CLI -a |
− | if | + | if [ $lang_2_chan -gt 2 ] |
# more than 2 channels present | # more than 2 channels present | ||
#pass through track without transcoding,perfect quality | #pass through track without transcoding,perfect quality | ||
Line 314: | Line 358: | ||
fi | fi | ||
else | else | ||
− | echo "No track found for $lang_2" >> "$logfile" | + | echo "No track found for $lang_2 = $lang2_name" >> "$logfile" |
fi | fi | ||
− | if | + | if [ $lang_3_count -ge 1 ] |
then | then | ||
echo "Selected track $lang_3_track for $lang_3" >> "$logfile" | echo "Selected track $lang_3_track for $lang_3" >> "$logfile" | ||
− | if $audiotacks | + | if [ -z "$audiotacks" ] |
#no track for first or second language present | #no track for first or second language present | ||
then | then | ||
− | audiotacks="$ | + | audiotacks="$lang_3_track" #Handbrake_CLI -a |
− | if | + | if [ $lang_3_chan -gt 2 ] |
# more than 2 channels present | # more than 2 channels present | ||
#pass through track without transcoding,perfect quality | #pass through track without transcoding,perfect quality | ||
Line 339: | Line 383: | ||
else | else | ||
#previous track present, append | #previous track present, append | ||
− | audiotacks="$audiotracks,$ | + | audiotacks="$audiotracks,$lang_3_track" #Handbrake_CLI -a |
− | if | + | if [ $lang_3_chan -gt 2 ] |
# more than 2 channels present | # more than 2 channels present | ||
#pass through track without transcoding,perfect quality | #pass through track without transcoding,perfect quality | ||
Line 356: | Line 400: | ||
fi | fi | ||
else | else | ||
− | echo "No track found for $lang_3" >> "$logfile" | + | echo "No track found for $lang_3 = $lang3_name" >> "$logfile" |
fi | fi | ||
+ | echo "Finished Audio Selection" >> "$logfile" | ||
#################FINISHED AUDIO TRACK SELECTION############ | #################FINISHED AUDIO TRACK SELECTION############ | ||
Line 386: | Line 431: | ||
# There were errors in the Handbrake Run. | # There were errors in the Handbrake Run. | ||
then | then | ||
− | scriptstoptime=$(date +%F-%H | + | scriptstoptime=$(date +%F-%H%M%S) |
echo "Transcoding-Error at $scriptstoptime" >> "$logfile" | echo "Transcoding-Error at $scriptstoptime" >> "$logfile" | ||
echo "Interrupted file $outfile" >> "$logfile" | echo "Interrupted file $outfile" >> "$logfile" | ||
Line 405: | Line 450: | ||
if [ ! -f "$outfile" ]; | if [ ! -f "$outfile" ]; | ||
then | then | ||
− | scriptstoptime=$(date +%F-%H | + | scriptstoptime=$(date +%F-%H%M%S) |
echo "Output-Error at $scriptstoptime" >> "$logfile" | echo "Output-Error at $scriptstoptime" >> "$logfile" | ||
echo "Ausgabedatei $outfile existiert nicht" >> "$logfile" | echo "Ausgabedatei $outfile existiert nicht" >> "$logfile" | ||
Line 444: | Line 489: | ||
] | ] | ||
# better option would be to pull the commercial-free flag from the database, but | # better option would be to pull the commercial-free flag from the database, but | ||
− | # then | + | # then I got advised against manual access to the database when using a language |
# such as bash with no mysql support. | # such as bash with no mysql support. | ||
then | then | ||
− | #This is a channel without commercials | + | #This is a channel without commercials, encoding to X264 |
echo "Userjob SD-TV ohne Werbung startet" >> "$logfile" | echo "Userjob SD-TV ohne Werbung startet" >> "$logfile" | ||
HandBrakeCLI -q 19.0 -e x264 -r 25 -a "$audiotacks" -A "$audioname" -E "$audiocodec" -B "$audiobitrate" -6 "$audiodownmix" -f mp4 --crop 0:0:0:0 -d -m -x b-adapt=2:rc-lookahead=50:ref=3:bframes=3:me=umh:subme=8:trellis=1:merange=20:direct=auto -i "$mythrecordingsdir/$file" -o "$outfile" -4 --optimize 2>> "$logfile" | HandBrakeCLI -q 19.0 -e x264 -r 25 -a "$audiotacks" -A "$audioname" -E "$audiocodec" -B "$audiobitrate" -6 "$audiodownmix" -f mp4 --crop 0:0:0:0 -d -m -x b-adapt=2:rc-lookahead=50:ref=3:bframes=3:me=umh:subme=8:trellis=1:merange=20:direct=auto -i "$mythrecordingsdir/$file" -o "$outfile" -4 --optimize 2>> "$logfile" | ||
Line 453: | Line 498: | ||
# There were errors in the Handbrake Run. | # There were errors in the Handbrake Run. | ||
then | then | ||
− | scriptstoptime=$(date +%F-%H | + | scriptstoptime=$(date +%F-%H%M%S) |
echo "Transcoding-Error at $scriptstoptime" >> "$logfile" | echo "Transcoding-Error at $scriptstoptime" >> "$logfile" | ||
echo "Broken File $outfile" >> "$logfile" | echo "Broken File $outfile" >> "$logfile" | ||
Line 483: | Line 528: | ||
# There were errors in the Handbrake Run. | # There were errors in the Handbrake Run. | ||
then | then | ||
− | scriptstoptime=$(date +%F-%H | + | scriptstoptime=$(date +%F-%H%M%S) |
echo "Transcoding-Error at $scriptstoptime" >> "$logfile" | echo "Transcoding-Error at $scriptstoptime" >> "$logfile" | ||
echo "Broken File $outfile" >> "$logfile" | echo "Broken File $outfile" >> "$logfile" | ||
Line 506: | Line 551: | ||
fi | fi | ||
− | scriptstoptime=$(date +%F-%H | + | scriptstoptime=$(date +%F-%H%M%S) |
echo "Successfully finished at $scriptstoptime" >> "$logfile" | echo "Successfully finished at $scriptstoptime" >> "$logfile" | ||
echo "Transcoded file: $outfile" >> "$logfile" | echo "Transcoded file: $outfile" >> "$logfile" | ||
Line 512: | Line 557: | ||
#Transcoding now done, following is some maintenance work | #Transcoding now done, following is some maintenance work | ||
chown mythtv:mythtv "$outfile" | chown mythtv:mythtv "$outfile" | ||
+ | |||
+ | |||
exit 0 | exit 0 | ||
</pre> | </pre> |
Latest revision as of 05:03, 11 July 2013
This script shall be called as MythTV user job. It transcodes the DVB recordings (mpeg files) using Handbrake.
Contents
Overview
Features
- On a Phenom II X4 2,8Ghz it is a lot faster than mythnuv2mkv using comparable quality settings. With Mythbrake I get ~40fps for 720p HDTV and around ~250fps on SDTV without noticable quality degradation compared to the source file.
- One reason for the speed is that Mythbrake can preserve anamorphic pixels, thus saving on resizing. mythnuv2mkv insists on resizing to square pixels, increasing file size and encoding time.
- All transcodings are single pass with constant quality as this results in the same quality as with dual pass but without the need for a second pass. This further increases the speed adavantage. The only downside compared to dual pass is a slightly less predictable file size. As burning files to optical media (with a fixed size) is imho a thing of the past, exact file size hardly matters though.
- Can transcode using mutiple languages (up to 3)
- Preserves surround sound (e.g. AC3 5.1)
- Alerts via email in case of an error, so no problems lurk in the dark until the recording sheduled for transcoding is overwritten with newer recordings.
Notes
- I have no programming education and my job has nothing to do with computing. I wrote this script from what I learned from google and reading man pages. It is wirtten primarily for my own purposes to extend the lovely mythtv. It may not match your needs, but perhaps someone else's. This script may contain bugs, do things in suboptimal ways or eat your cat, be prepared and careful.
- Because of the above, the script is written in bash. This is suboptimal in some ways (e.g. answering the question wether a channel has commercials) but on the other hand has little requirements and might be easier to understand to new users.
- This script is tested on RHEL6 (Sientific Linux) with MythTV Ver. 0.25 and 0.26 from the atrpms repository.
- If you find any bugs or problems feel free to mail me at ares.drake@gmail.com
Requirements
- Handbrake is used for the transcoding and needs to be installed on your machine. See the handbrake website for installation details.
- Mediainfo is used for probing the source file (i.e. the recording) what audio tracks are available and wether the recoding is HDTV. Download on their website.
Source Formats
HDTV will be reencoded with Mpeg4 AVC H264 to save space. All HDTV channels I can receive here in Germany are without commercials, so I don't bother running mythcommflag on them. In case your situation differs you'll have to modify the script.
SDTV will have commercials cut out if necessary and will then be transcoded to Mpeg4 ASP (H263, Xvid, DivX). The scipt will check the ChanID of the recording to decide wethere there are commercials, so you have to adapt the list of ChanIDs to your setup. If the ChanID indicates the source file contains commercials, I use Mpeg4 ASP instead of Mpeg4 AVC on SDTV recordings because the transcoding is much faster and it is easier to cut later on as mythcommflag isn't perfect. For manual cutting afterwards I use Avidemux. If no commercials are present, the SDTV recordings are transcoded to H264 as well.
Audio: You can pass this script up to three languages and corresponding descriptions. The script will then automatically search the source file for the best track (i.e. the track with the most channels, e.g. 5.1 is better than stereo) for each given language. Surround sound is preserved, tracks with more than 2 channels are passed through without audio transcoding, mono or stereo tracks are transcoded to 128kbits/sec.
Change Logs
Version 1.3b
- 5 November 2012
- Bugfixes
Version 1.3
- 8 May 2012
- Support multiple languages (auto-searches matching track for each given language)
- Automatically uses passthrough on surround sound (e.g. AC3 5.1)
Version 1.2
- Include source file check
Version 1.1
- Change Container from MKV to MP4 optimized for streaming, reason: Compatibility with Philips UPnP Clients
- Updated to use %DIR% instead of fixed path
- some cleanup
Version 1.0
- Inital release
Scripts
Note: For MythTV versions 0.25 and older, "%STARTTIMEUTC%" needs to be changed to "%STARTTIME%"
Version 1.3b
#!/bin/bash # Save this as mythbrake.sh and make the file executable # Written by Ares Drake, ares.drake@gmail.com # Licenced under GPL v3 # This Script shall be called as MythTV user job. It transcodes the DVB recordings (mpeg files) using Handbrake. It first checks whether the recording is HDTV. If so it will be reencoded with H.264 to save space. SDTV will have commercials cut out if necessary and will then be transcoded to H.263 (Xvid, DivX). # #USAGE:###################### # This Sript shall be called as a MythTV user job like as follows: # /path/to/mythbrake.sh "%DIR%" "%FILE%" "%CHANID%" "%STARTTIMEUTC%" "%TITLE%" "%SUBTITLE%" "%CATEGORY%" ############################# # # #REQUIREMENTS################ # You need to have the following programs installed: # mediainfo: http://mediainfo.sourceforge.net/ # handbrake with dependencies: http://www.handbrake.fr # Installation of these is convered on their sites ############################# ######SOME CONSTANSTS FOR USER EDITING###### ############################################ logdir="/opt/mythtv/transcodelogs" #change to your needs for logs errormail="youremail@adress.com" # this email address will be informed in case of errors outdir="/where/you/want/it" # specify directory where you want the transcoded file to be placed #Audio track (language) selection, your values must match the output syntax of mediainfo #check "mediainfo --Inform="Audio;%Language/String% yoursourcefile.mpg" in the terminal for syntax lang_1="German" #Primary language you want to keep lang_2="qaa" #Secondary language you want to keep, use "none" to skip, quaa is original language, wich is English most of the time lang_3="French" #Thid language you want to keep, use "none" to skip lang1_name="Deutsch" #This is the label of the 1st audio stream inside the final video file lang2_name="Englisch" #This is the label of the 2nd audio stream inside the final video file lang3_name="Französisch" #This is the label of the 3rd audio stream inside the final video file ######END constants for user editing###### ######DEFINE SOME BASIC VARIABLES###### ####################################### scriptstarttime=$(date +%F-%H%M%S) mythrecordingsdir="$1" # specify directory where MythTV stores its recordings file="$2" # using sed to sanitize the variables to avoid problematic file names, only alphanumerical, space, hyphen and underscore allowed, other characters are transformed to underscore subtitle="$(echo "$6" | sed 's/[^A-Za-z0-9_ -]/_/g')" title="$(echo "$5" | sed 's/[^A-Za-z0-9_ -]/_/g')" category="$(echo "$7" | sed 's/[^A-Za-z0-9_ -]/_/g')" chanid="$3" starttime="$4" if [ -z "$category" ] then category="Unbekannt" #name for unknown category, Unbekannt is German for unknown fi logfile="$logdir/$scriptstarttime-$title.log" touch "$logfile" chown mythtv:mythtv "$logfile" chmod a+rw "$logfile" filename="$title.mp4" # can be customized if [ -f "$outdir/$filename" ] # do not overwrite outfile, if already exists, change name then filename="$title-$scriptstarttime.mp4" fi outfile="$outdir/$filename" let lang_1_count=0 let lang_2_count=0 let lang_3_count=0 lang_1_track="" lang_2_track="" lang_3_track="" ######Variables finished ######DO SOME LOGGING###### ########################### echo "Transcode job $title starting at $scriptstarttime" >> "$logfile" echo "Original file: $mythrecordingsdir/$file" >> "$logfile" echo "Target file: $outfile" >> "$logfile" echo "ChanId: $chanid Time: $starttime" >> "$logfile" ######SOURCEFILE CHECK###### ############################ if [ ! -f "$mythrecordingsdir/$file" ] then #source file does not exist scriptstoptime=$(date +%F-%H%M%S) echo "Error at $scriptstoptime: Source file not found " >> "$logfile" echo "Maybe wrong path or missing permissions?" >> "$logfile" mail -s "Mythtv Sourcefile Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 fi ######MEDIAINFO CHECK###### ########################### fullmediainfo=(mediainfo $mythrecordingsdir/"$file") if [ $? != 0 ] # There were errors with Mediainfo. then scriptstoptime=$(date +%F-%H%M%S) echo "Error prior to encoding at $scriptstoptime" >> "$logfile" echo "Mediainfo encountered an error. Maybe mediainfo is not installed, or not in your path" >> "$logfile" echo "Mediainfo encountered an error. Maybe mediainfo is not installed, or not in your path" mail -s "Mythtv Mediainfo Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 else echo "Mediainfo Run successful." >> "$logfile" fi #######ANALAYZE AUDIO TRACKS AND DO LANGUAGE SELECTION###### ############################################################ acount=$(mediainfo --Inform="General;%AudioCount%" "$mythrecordingsdir/$file") #acount=number of audio tracks present in source file #Read all values into arrays bitrate="$(mediainfo --Inform="Audio;:%BitRate%" "$mythrecordingsdir/$file")" IFS=':' read -ra ARBITR <<< "$bitrate" language="$(mediainfo --Inform="Audio;:%Language/String%" "$mythrecordingsdir/$file")" IFS=':' read -ra ARLANG <<< "$language" channels="$(mediainfo --Inform="Audio;:%Channel(s)%" "$mythrecordingsdir/$file")" IFS=':' read -ra ARCHAN <<< "$channels" acodec="$(mediainfo --Inform="Audio;:%Format%" "$mythrecordingsdir/$file")" IFS=':' read -ra ARCODEC <<< "$acodec" #Finished building arrays echo "Array built successful, starting looping over audio tracks. There are $acount tracks, so we loop $acount times." >> "$logfile" for (( I=1; I <= "$acount"; I++ )) do #loop through all tracks, currently active track is $I #${ARBITR[$I]},${ARLANG[$I]},${ARCHAN[$I]},${ARCODEC[$I]} gives values for track $I echo "loop number $I." >> "$logfile" #select track for first language currentlang=${ARLANG[$I]} if [ "$currentlang" == "$lang_1" ] then echo -n "track $I matching $lang1_name" >> "$logfile" let "lang_1_count += 1" #let $lang_1_count = $lang_1_count+1 if [ $lang_1_count -eq 1 ] then #if this is the first track with desired language, we use it. echo " and is the first track matching" >> "$logfile" lang_1_track=$I let lang_1_chan="${ARCHAN[$I]}" lang_1_codec="${ARCODEC[$I]}" elif [ "${ARCHAN[$I]}" -gt "${ARCHAN[$lang_1_track]}" ] then echo " and is better than previous match" >> "$logfile" #there is already a track with the same desired language but this current track #has more channels, so we use this one instead of the previous track. lang_1_track=$I let lang_1_chan=${ARCHAN[$I]} lang_1_codec="${ARCODEC[$I]}" fi fi echo "Audio track1 iteration succesfull" >> "$logfile" #select track for second language if [ "$lang_2" != "none" ] then if [ "$currentlang" == "$lang_2" ] then echo -n "track $I matching $lang2_name" >> "$logfile" let "lang_2_count += 1" if [ $lang_2_count -eq 1 ] then #if this is the first track with desired language, we use it. echo " and is the first track matching" >> "$logfile" let lang_2_track=$I let lang_2_chan="${ARCHAN[$I]}" lang_2_codec="${ARCODEC[$I]}" elif [ "${ARCHAN[$I]}" -gt "${ARCHAN[$lang_2_track]}" ] then echo " and is better than previous match" >> "$logfile" #there is already a track with the same desired language but this current track #has more channels, so we use this one instead of the previous track. let lang_2_track=$I let lang_2_chan=${ARCHAN[$I]} lang_2_codec="${ARCODEC[$I]}" fi fi fi echo "Audio track2 iteration succesfull" >> "$logfile" if [ "$lang_3" != "none" ] then #select track for third language if [ "$currentlang" == "$lang_3" ] then echo -n "track $I matching $lang3_name" >> "$logfile" let "lang_3_count += 1" if [ $lang_3_count -eq 1 ] then #if this is the first track with desired language, we use it. echo " and is the first track matching" >> "$logfile" let lang_3_track=$I let lang_3_chan="${ARCHAN[$I]}" lang_3_codec="${ARCODEC[$I]}" elif [ "${ARCHAN[$I]}" -gt "${ARCHAN[$lang_3_track]}" ] then echo " and is better than previous match" >> "$logfile" #there is already a track with the same desired language but this current track #has more channels, so we use this one instead of the previous track. let lang_3_track=$I let lang_3_chan="${ARCHAN[$I]}" lang_3_codec="${ARCODEC[$I]}" fi fi fi echo "Audio track3 iteration succesfull" >> "$logfile" done echo "Audio track iteration succesfull" >> "$logfile" #okay, how may tracks to include in the outfile now? let totallangcount=($lang_1_count + $lang_2_count + $lang_3_count) if [ $totallangcount -eq 0 ] # No suitable audio track found. then scriptstoptime=$(date +%F-%H%M%S) echo "Audio track error at $scriptstoptime" >> "$logfile" echo "The script was unable to find a matching audio track, aborting." >> "$logfile" mail -s "Mythtv Audio Track Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 else echo "Audio selection successful." >> "$logfile" fi echo "Total number of tracks selected: $totallangcount" >> "$logfile" ###Now generate Handbrake commands from the above#### if [ $lang_1_count -ge 1 ] then echo "Selected track $lang_1_track for $lang_1" >> "$logfile" audiotacks="$lang_1_track" #Handbrake_CLI -a if [ $lang_1_chan -gt 2 ] # more than 2 channels present, pass through track without transcoding,perfect quality then audioname="$lang1_name-Surround" #Handbrake_CLI -A audiocodec="copy" #Handbrake_CLI -E audiobitrate="auto" #Handbrake_CLI -B audiodownmix="auto" #Handbrake_CLI -6 else audioname="$lang1_name-Stereo" audiocodec="faac" audiobitrate="128" audiodownmix="stereo" fi else echo "No track found for $lang_1 = $lang1_name" >> "$logfile" fi if [ $lang_2_count -ge 1 ] then echo "Selected track $lang_2_track for $lang_2" >> "$logfile" if [ -z "$audiotacks" ] #no track for first language present then audiotacks="$lang_2_track" #Handbrake_CLI -a if [ $lang_2_chan -gt 2 ] # more than 2 channels present #pass through track without transcoding,perfect quality then audioname="$lang2_name-Surround" #Handbrake_CLI -A audiocodec="copy" #Handbrake_CLI -E audiobitrate="auto" #Handbrake_CLI -B audiodownmix="auto" #Handbrake_CLI -6 else audioname="$lang2_name-Stereo" audiocodec="faac" audiobitrate="128" audiodownmix="stereo" fi else #first track present, append audiotacks="$audiotracks,$lang_2_track" #Handbrake_CLI -a if [ $lang_2_chan -gt 2 ] # more than 2 channels present #pass through track without transcoding,perfect quality then audioname="$audioname,$lang2_name-Surround" #Handbrake_CLI -A audiocodec="$audiocodec,copy" #Handbrake_CLI -E audiobitrate="$audiobitrate,auto" #Handbrake_CLI -B audiodownmix="$audiodownmix,auto" #Handbrake_CLI -6 else audioname="$audioname,$lang2_name-Stereo" audiocodec="$audiocodec,faac" audiobitrate="$audiobitrate,128" audiodownmix="$audiodownmix,stereo" fi fi else echo "No track found for $lang_2 = $lang2_name" >> "$logfile" fi if [ $lang_3_count -ge 1 ] then echo "Selected track $lang_3_track for $lang_3" >> "$logfile" if [ -z "$audiotacks" ] #no track for first or second language present then audiotacks="$lang_3_track" #Handbrake_CLI -a if [ $lang_3_chan -gt 2 ] # more than 2 channels present #pass through track without transcoding,perfect quality then audioname="$lang3_name-Surround" #Handbrake_CLI -A audiocodec="copy" #Handbrake_CLI -E audiobitrate="auto" #Handbrake_CLI -B audiodownmix="auto" #Handbrake_CLI -6 else audioname="$lang3_name-Stereo" audiocodec="faac" audiobitrate="128" audiodownmix="stereo" fi else #previous track present, append audiotacks="$audiotracks,$lang_3_track" #Handbrake_CLI -a if [ $lang_3_chan -gt 2 ] # more than 2 channels present #pass through track without transcoding,perfect quality then audioname="$audioname,$lang3_name-Surround" #Handbrake_CLI -A audiocodec="$audiocodec,copy" #Handbrake_CLI -E audiobitrate="$audiobitrate,auto" #Handbrake_CLI -B audiodownmix="$audiodownmix,auto" #Handbrake_CLI -6 else audioname="$audioname,$lang3_name-Stereo" audiocodec="$audiocodec,faac" audiobitrate="$audiobitrate,128" audiodownmix="$audiodownmix,stereo" fi fi else echo "No track found for $lang_3 = $lang3_name" >> "$logfile" fi echo "Finished Audio Selection" >> "$logfile" #################FINISHED AUDIO TRACK SELECTION############ echo "$audiotacks, $audioname, $audiocodec, $audiobitrate, $audiodownmix" echo "$audiotacks, $audioname, $audiocodec, $audiobitrate, $audiodownmix" >> "$logfile" #HandBrakeCLI -q 19.0 -e x264 -r 25 -a $audiotacks -A $audioname -E $audiocodec -B $audiobitrate -6 $audiodownmix -f mp4 --crop 0:0:0:0 -d -m -x b-adapt=2:rc-lookahead=50:ref=3:bframes=3:me=umh:subme=8:trellis=1:merange=20:direct=auto -i "$mythrecordingsdir/$file" -o "$outfile" -4 --optimize 2>> "$logfile" #################### #get width: you need mediainfo installed, see mediainfo.sourceforge.net width=$(mediainfo --Inform="Video;%Width%" "$mythrecordingsdir/$file") ############################################################## ### Transcoding starts here, in 3 differend versions: HDTV w/o commercials, SDTV w/ and w/o commercials. # width >=1280 # currently this can only be ARD HD, ZDF HD or ARTE HD, so no commercials # Userjob for HDTV: Re-Encode in AVC H.264: saves space, but keeps H.264, x264 via HandbrakeCLI if [ $width -ge 1280 ] then echo "Userjob HD-TV starts because of with of $width" >> "$logfile" HandBrakeCLI -q 19.0 -e x264 -r 25 -a "$audiotacks" -A "$audioname" -E "$audiocodec" -B "$audiobitrate" -6 "$audiodownmix" -f mp4 --crop 0:0:0:0 -d -m -x b-adapt=2:rc-lookahead=50:ref=3:bframes=3:me=umh:subme=8:trellis=1:merange=20:direct=auto -i "$mythrecordingsdir/$file" -o "$outfile" -4 --optimize 2>> "$logfile" if [ $? != 0 ] # There were errors in the Handbrake Run. then scriptstoptime=$(date +%F-%H%M%S) echo "Transcoding-Error at $scriptstoptime" >> "$logfile" echo "Interrupted file $outfile" >> "$logfile" echo "###################################" >> "$logfile" echo $fullmediainfo >> "$logfile" echo "###################################" >> "$logfile" outmediainfo=(mediainfo "$outfile") echo $outmediainfo >> "$logfile" echo "###################################" >> "$logfile" mail -s "Mythtv Transcoding Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 else echo "Transcode Run successfull." >> "$logfile" file "$outfile" >> "$logfile" fi #check if outfile exists if [ ! -f "$outfile" ]; then scriptstoptime=$(date +%F-%H%M%S) echo "Output-Error at $scriptstoptime" >> "$logfile" echo "Ausgabedatei $outfile existiert nicht" >> "$logfile" echo "###################################" >> "$logfile" echo $fullmediainfo >> "$logfile" echo "###################################" >> "$logfile" outmediainfo=(mediainfo "$outfile") echo $outmediainfo >> "$logfile" echo "###################################" >> "$logfile" mail -s "Mythtv Ausgabedatei Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 fi #width <= 720 elif [ $width -le 720 ] then # this is SDTV, so it could be either with or without commercials. We check for commercials by comparing to ChanID list. if [ #ChanID without commercials $chanid == 3007 -o #3sat $chanid == 29014 -o #zdf neo $chanid == 30014 -o #zdf neo $chanid == 30107 -o #BayrFS $chanid == 29110 -o #BR $chanid == 30110 -o #BR $chanid == 30113 -o #SWR-BW $chanid == 30111 -o #WDR $chanid == 30230 -o #MDR $chanid == 30206 -o #rbb $chanid == 29205 -o #rbb $chanid == 29206 -o #rbb $chanid == 29205 -o #rbb $chanid == 29486 -o #SR $chanid == 30107 -o #BayrFS ] # better option would be to pull the commercial-free flag from the database, but # then I got advised against manual access to the database when using a language # such as bash with no mysql support. then #This is a channel without commercials, encoding to X264 echo "Userjob SD-TV ohne Werbung startet" >> "$logfile" HandBrakeCLI -q 19.0 -e x264 -r 25 -a "$audiotacks" -A "$audioname" -E "$audiocodec" -B "$audiobitrate" -6 "$audiodownmix" -f mp4 --crop 0:0:0:0 -d -m -x b-adapt=2:rc-lookahead=50:ref=3:bframes=3:me=umh:subme=8:trellis=1:merange=20:direct=auto -i "$mythrecordingsdir/$file" -o "$outfile" -4 --optimize 2>> "$logfile" if [ $? != 0 ] # There were errors in the Handbrake Run. then scriptstoptime=$(date +%F-%H%M%S) echo "Transcoding-Error at $scriptstoptime" >> "$logfile" echo "Broken File $outfile" >> "$logfile" echo "###################################" >> "$logfile" echo $fullmediainfo >> "$logfile" mail -s "Mythtv Transcoding Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 else echo "Transcode Run successful." >> "$logfile" fi else # We have a channel with commercials, so flag & cut them out first. echo "Userjob SD-TV mit Werbung startet" >> "$logfile" /usr/bin/mythcommflag -c "$chanid" -s "$starttime" --gencutlist /usr/bin/mythtranscode --chanid "$chanid" --starttime "$starttime" --mpeg2 --honorcutlist /usr/bin/mythcommflag --file "$file" --rebuild #Finished commercial cutting, following is encoding as above #SD-TV Userjob is encoding to MPEG4 ASP aka DivX aka Xvid via FFMPEG via HandBrakeCLI # $SDCCMDLINE is the commandline for SDtv-Commercials SDCCMDLINE='/usr/bin/HandBrakeCLI -q 3 -r 25 -a $audiotacks -A $audioname -E $audiocodec -B $audiobitrate -6 $audiodownmix -f mp4 --crop 0:0:0:0 -d -m -i "$mythrecordingsdir/$file" -o "$outfile" --optimize 2>> "$logfile"' echo "Commandline: $SDCCMDLINE" >> "$logfile" HandBrakeCLI -q 3 -r 25 -a "$audiotacks" -A "$audioname" -E "$audiocodec" -B "$audiobitrate" -6 "$audiodownmix" -f mp4 --crop 0:0:0:0 -d -m -i "$mythrecordingsdir/$file" -o "$outfile" --optimize 2>> "$logfile" if [ $? != 0 ] # There were errors in the Handbrake Run. then scriptstoptime=$(date +%F-%H%M%S) echo "Transcoding-Error at $scriptstoptime" >> "$logfile" echo "Broken File $outfile" >> "$logfile" echo "###################################" >> "$logfile" echo $fullmediainfo >> "$logfile" mail -s "Mythtv Transcoding Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 else echo "Transcode Run successful." >> "$logfile" fi fi #720<width<1280 or error getting width: dunno whats going on here, abort else echo "Error: 720<width<1280, undefined condition, aborting" >> "$logfile" echo "###################################" >> "$logfile" echo $fullmediainfo >> "$logfile" mail -s "Mythtv Transcoding Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 fi scriptstoptime=$(date +%F-%H%M%S) echo "Successfully finished at $scriptstoptime" >> "$logfile" echo "Transcoded file: $outfile" >> "$logfile" #Transcoding now done, following is some maintenance work chown mythtv:mythtv "$outfile" exit 0
Version 1.2
# Version 1.2 #!/bin/bash # Save this as mythbrake.sh and make the file executable # Written by Ares Drake, ares.drake@gmail.com # Licenced under GPL v3 # This Script shall be called as MythTV user job. It transcodes the DVB recordings (mpeg files) using Handbrake. It first checks whether the recording is HDTV. If so it will be reencoded with H.264 to save space. SDTV will have commercials cut out if necessary and will then be transcoded to H.263 (Xvid, DivX). # #USAGE:###################### # This Sript shall be called as a MythTV user job like as follows: # /path/to/mythbrake.sh "%DIR%" "%FILE%" "%CHANID%" "%STARTTIME%" "%TITLE%" "%SUBTITLE%" ############################# # # #REQUIREMENTS################ # You need to have the following programs installed: # mediainfo: http://mediainfo.sourceforge.net/ # handbrake with dependencies: http://www.handbrake.fr ############################# ###Some constants for user editing logdir="/opt/mythtv/transcodelogs" errormail="youremail@adress.com" # this email address will be informed in case of errors outdir="/where/you/want/it" # specify directory where you want the transcoded file to be placed audiostreamname="Deutsch-Stereo" #This is the label of the audio stream inside the final video file ###Define some basic variables scriptstarttime=$(date +%F-%H%M%S) mythrecordingsdir="$1" # specify directory where MythTV stores its recordings file="$2" chanid="$3" starttime="$4" title="$(echo "$5" | sed 's/(//g' | sed 's/)//g' | sed 's/:/_/g' | sed 's%/%_%g')" subtitle="$(echo "$6" | sed 's/(//g' | sed 's/)//g' | sed 's/://g' | sed 's%/%_%g')" logfile="$logdir/$scriptstarttime-$title.log" touch "$logfile" chown mythtv:mythtv "$logfile" chmod a+rw "$logfile" filename="$title.mp4" # can be customized if [ -f "$outdir/$filename" ] # do not overwrite outfile, if already exists, change name then filename="filename-$scriptstarttime" fi outfile="$outdir/$filename" ###Do some logging echo "Transcode job $title starting at $scriptstarttime" >> "$logfile" echo "Original file: $mythrecordingsdir/$file" >> "$logfile" echo "Target file: $outfile" >> "$logfile" echo "ChanId: $chanid Time: $starttime" >> "$logfile" #Source file check if [ ! -f "$mythrecordingsdir/$file" ]; then #source file does not exist scriptstoptime=$(date +%F-%H:%M:%S) echo "Error at $scriptstoptime: Source file not found " >> "$logfile" echo "Maybe wrong path or missing permissions?" >> "$logfile" mail -s "Mythtv Sourcefile Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 fi #################### #get width: you need mediainfo installed, see mediainfo.sourceforge.net width=$(mediainfo --Inform="Video;%Width%" "$mythrecordingsdir/$file") if [ $? != 0 ] # There were errors with Mediainfo. then scriptstoptime=$(date +%F-%H:%M:%S) echo "Error prior to encoding at $scriptstoptime" >> "$logfile" echo "Mediainfo encountered an error. Maybe mediainfo is not installed, or not in your path" >> "$logfile" echo "Mediainfo encountered an error. Maybe mediainfo is not installed, or not in your path" mail -s "Mythtv Mediainfo Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 else echo "Mediainfo Run successful." >> "$logfile" fi fullmediainfo=(mediainfo $mythrecordingsdir/"$file") ############################################################## ### Transcoding starts here, in 3 differend versions: HDTV w/o commercials, SDTV w/ and w/o commercials. # width >=1280 # currently this can only be ARD HD, ZDF HD or ARTE HD, so no commercials # Userjob for HDTV: Re-Encode in AVC H.264: saves space, but keeps H.264, x264 via HandbrakeCLI if [ $width -ge 1280 ] then echo "Userjob HD-TV starts because of with of $width" >> "$logfile" # $HDCMDLINE is the commandline for HDTV HDCMDLINE='HandBrakeCLI -q 20.0 -e x264 -r 25 -a 1 -A $audiostreamname -E MP3 -B 128 -R 48 --mixdown dpl2 -f mp4 --crop 0:0:0:0 -d -m -x b-adapt=2:rc-lookahead=50:ref=3:bframes=3:me=umh:subme=8:trellis=1:merange=20:direct=auto -i "$mythrecordingsdir/$file" -o "$outfile" --optimize 2>> "$logfile"' HandBrakeCLI -q 20.0 -e x264 -r 25 -a 1 -A $audiostreamname -E MP3 -B 128 -R 48 --mixdown dpl2 -f mp4 --crop 0:0:0:0 -d -m -x b-adapt=2:rc-lookahead=50:ref=3:bframes=3:me=umh:subme=8:trellis=1:merange=20:direct=auto -i "$mythrecordingsdir/$file" -o "$outfile" --optimize 2>> "$logfile" if [ $? != 0 ] # There were errors in the Handbrake Run. then scriptstoptime=$(date +%F-%H:%M:%S) echo "Transcoding-Error at $scriptstoptime" >> "$logfile" echo "Interrupted file $outfile" >> "$logfile" echo "###################################" >> "$logfile" echo $fullmediainfo >> "$logfile" mail -s "Mythtv Transcoding Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 else echo "Transcode Run successfull." >> "$logfile" fi #width <= 720 elif [ $width -le 720 ] then # this is SDTV, so it could be either with or without commercials. We check for commercials by comparing to ChanID list. if [ $chanid == 3007 -o $chanid == 29014 -o $chanid == 30014 -o $chanid == 30107 ] #ChanID without commercials: 3007 3sat; ZDF info; 29014 & 3014 ZDF neo; ZDF theater; 30107 BayrFS Nord; BayrFS Süd; SWR BW; RBB Berlin; WDR Köln; BR alpha; SR # better option would be to pull the commercial-free flag from the database, but # then i would advise against manual access to the database when using a language # such as bash with no mysql support. then #This is a channel without commercials echo "Userjob SD-TV ohne Werbung startet" >> "$logfile" #SD-TV Userjob is encoding to MPEG4 ASP aka DivX aka Xvid via FFMPEG via HandBrakeCLI # $SDFCMDLINE is the commandline for SDtv-commercialFree SDFCMDLINE="/usr/bin/HandBrakeCLI -q 3 -r 25 -a 1 -A $audiostreamname -E MP3 -B 128 -R 48 --mixdown dpl2 -f mp4 --crop 0:0:0:0 -d -m -i $mythrecordingsdir/$file -o $outfile --optimize" echo "Commandline: $SDFCMDLINE" >> "$logfile" HandBrakeCLI -q 3 -r 25 -a 1 -A $audiostreamname -E MP3 -B 128 -R 48 --mixdown dpl2 -f mp4 --crop 0:0:0:0 -d -m -i "$mythrecordingsdir/$file" -o "$outfile" --optimize 2>> "$logfile" if [ $? != 0 ] # There were errors in the Handbrake Run. then scriptstoptime=$(date +%F-%H:%M:%S) echo "Transcoding-Error at $scriptstoptime" >> "$logfile" echo "Broken File $outfile" >> "$logfile" echo "###################################" >> "$logfile" echo $fullmediainfo >> "$logfile" mail -s "Mythtv Transcoding Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 else echo "Transcode Run successful." >> "$logfile" fi else # We have a channel with commercials, so flag & cut them out first. echo "Userjob SD-TV mit Werbung startet" >> "$logfile" /usr/bin/mythcommflag -c "$chanid" -s "$starttime" --gencutlist /usr/bin/mythtranscode --chanid "$chanid" --starttime "$starttime" --mpeg2 --honorcutlist /usr/bin/mythcommflag --file "$file" --rebuild #Finished commercial cutting, following is encoding as above #SD-TV Userjob is encoding to MPEG4 ASP aka DivX aka Xvid via FFMPEG via HandBrakeCLI # $SDCCMDLINE is the commandline for SDtv-Commercials SDCCMDLINE='/usr/bin/HandBrakeCLI -q 3 -r 25 -a 1 -A $audiostreamname -E MP3 -B 128 -R 48 --mixdown dpl2 -f mp4 --crop 0:0:0:0 -d -m -i "$mythrecordingsdir/$file" -o "$outfile" --optimize 2>> "$logfile"' echo "Commandline: $SDCCMDLINE" >> "$logfile" HandBrakeCLI -q 3 -r 25 -a 1 -A $audiostreamname -E MP3 -B 128 -R 48 --mixdown dpl2 -f mp4 --crop 0:0:0:0 -d -m -i "$mythrecordingsdir/$file" -o "$outfile" --optimize 2>> "$logfile" if [ $? != 0 ] # There were errors in the Handbrake Run. then scriptstoptime=$(date +%F-%H:%M:%S) echo "Transcoding-Error at $scriptstoptime" >> "$logfile" echo "Broken File $outfile" >> "$logfile" echo "###################################" >> "$logfile" echo $fullmediainfo >> "$logfile" mail -s "Mythtv Transcoding Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 else echo "Transcode Run successful." >> "$logfile" fi fi #720<width<1280 or error getting width: dunno whats going on here, abort else echo "Error: 720<width<1280, undefined condition, aborting" >> "$logfile" echo "###################################" >> "$logfile" echo $fullmediainfo >> "$logfile" mail -s "Mythtv Transcoding Error on $HOSTNAME" "$errormail" < "$logfile" mv "$logfile" "$logfile-FAILED" exit 1 fi scriptstoptime=$(date +%F-%H:%M:%S) echo "Successfully finished at $scriptstoptime" >> "$logfile" echo "Transcoded file: $outfile" >> "$logfile" exit 0