This cron job is run as my regular user, the same one who uses MythFrontend
$ crontab -l
36 * * * * nice ~/.shepherd/shepherd --daily --quiet && nice /usr/bin/mythfilldatabase --update --file --sourceid 1 --xmlfile ~/.shepherd/output.xmltv --quiet 2>&1> /dev/null
Showing posts with label scripts. Show all posts
Showing posts with label scripts. Show all posts
Saturday, October 26, 2013
Tuesday, May 8, 2012
kill processes with kill-byname.sh
#!/bin/bash
# kill-byname.sh: Killing processes by name.
# Compare this script with kill-process.sh.
# For instance,
#+ try "./kill-byname.sh xterm" --
#+ and watch all the xterms on your desktop disappear.
# Warning:
# -------
# This is a fairly dangerous script.
# Running it carelessly (especially as root)
#+ can cause data loss and other undesirable effects.
E_BADARGS=66
if test -z "$1" # No command-line arg supplied?
then
echo "Usage: `basename $0` Process(es)_to_kill"
exit $E_BADARGS
fi
PROCESS_NAME="$1"
ps ax | grep "$PROCESS_NAME" | awk '{print $1}' | xargs -i kill {} 2&>/dev/null
# ^^ ^^
# ---------------------------------------------------------------
# Notes:
# -i is the "replace strings" option to xargs.
# The curly brackets are the placeholder for the replacement.
# 2&>/dev/null suppresses unwanted error messages.
#
# Can grep "$PROCESS_NAME" be replaced by pidof "$PROCESS_NAME"?
# ---------------------------------------------------------------
exit $?
# The "killall" command has the same effect as this script,
#+ but using it is not quite as educational.
Tuesday, April 17, 2012
Clone Arch root
This script will make a clone of my root directory onto a mounted partition. It is far from perfect!
It requires my root /etc/fstab plus a "clone-version" /etc/fstabClone (see below)
It requires folders /mnt/ssdRootClone on the original and /mnt/ssdRoot on the Clone.
I run it as root.
##############################################################################
#!/bin/bash
# fileinfo.sh
LOG="/var/log/cloneArch.log"
date=`date "+%a %b %e %H:%M:%S %Y"`
DESTINATION="/mnt/ssdRootClone"
#DESTINATION="/home/david/Clone"
FSTAB="/etc/fstab"
FSTABCLONE="/etc/fstabClone"
FILES="/bin
/boot
/dev
/etc
/lib
/lib64
/opt
/root
/run
/sbin
/srv
/tmp
/usr
/var"
FOLDERTOREMOVE="$DESTINATION/boot/grub/grub"
echo "$date : " >>$LOG
echo "$date : System is being cloned." >>$LOG
echo "$date : Clone mounted at $DESTINATION" >>$LOG
echo "$date : " >>$LOG
# Clear the variable directpries from the destination first
#rm -rf $DESTINATION/tmp
#rm -rf $DESTINATION/var
for file in $FILES
do
if [ ! -e "$file" ] # Check if file exists.
then
echo "$date : $file does not exist and has not been cloned." >>$LOG
else
# Clone the system here
echo "$date : $file is next." >>$LOG
# rsync options used
#
# -a, --archive
# This is equivalent to -rlptgoD. It is a quick way of saying you
# want recursion and want to preserve almost everything (with -H
# being a notable omission). The only exception to the above
# equivalence is when --files-from is specified, in which case -r
# is not implied.
#
# Note that -a does not preserve hardlinks, because finding multiply
# linked files is expensive. You must separately specify -H.
#
# -u, --update
# This forces rsync to skip any files which exist on the destination
# and have a modified time that is newer than the source file.
# (If an existing destination file has a modification time equal to
# the source file's, it will be updated if the sizes are different.)
#
# Note that this does not affect the copying of symlinks or other
# special files. Also, a difference of file format between the
# sender and receiver is always considered to be important enough
# for an update, no matter what date is on the objects. In other
# words, if the source has a directory where the destination has a
# file, the transfer would occur regardless of the timestamps.
#
# This option is a transfer rule, not an exclude, so it doesn't
# affect the data that goes into the file-lists, and thus it
# doesn't affect deletions. It just limits the files that the
# receiver requests to be transferred.
#
# -H, --hard-links
# This tells rsync to look for hard-linked files in the source and
# link together the corresponding files on the destination. With-
# out this option, hard-linked files in the source are treated as
# though they were separate files.
#
# This option does NOT necessarily ensure that the pattern of hard
# links on the destination exactly matches that on the source.
# Cases in which the destination may end up with extra hard links
# include the following:
#
#
# o If the destination contains extraneous hard-links (more
# linking than what is present in the source file list),
# the copying algorithm will not break them explicitly.
# However, if one or more of the paths have content differ-
# ences, the normal file-update process will break those
# extra links (unless you are using the --inplace option).
#
# o If you specify a --link-dest directory that contains hard
# links, the linking of the destination files against the
# --link-dest files can cause some paths in the destination
# to become linked together due to the --link-dest associa-
# tions.
#
#
# Note that rsync can only detect hard links between files that
# are inside the transfer set. If rsync updates a file that has
# extra hard-link connections to files outside the transfer, that
# linkage will be broken. If you are tempted to use the --inplace
# option to avoid this breakage, be very careful that you know how
# your files are being updated so that you are certain that no
# unintended changes happen due to lingering hard links (and see
# the --inplace option for more caveats).
#
# If incremental recursion is active (see --recursive), rsync may
# transfer a missing hard-linked file before it finds that another
# link for that contents exists elsewhere in the hierarchy. This
# does not affect the accuracy of the transfer (i.e. which files
# are hard-linked together), just its efficiency (i.e. copying the
# data for a new, early copy of a hard-linked file that could have
# been found later in the transfer in another member of the
# hard-linked set of files). One way to avoid this inefficiency
# is to disable incremental recursion using the --no-inc-recursive
# option.
rsync -aqHu --delete --stats --log-file=$LOG --log-file-format="%n" $file $DESTINATION
# make use of "$ du" command
# du -s $file | awk '{ print $2 "is " $1 }'
echo "$date : $file successfully cloned." >>$LOG
fi
done
# After cloning, fstab is going to mount the wrong partition
# Use the fstabClone for the corrected mounts.
if [ ! -e "$FSTABCLONE" ] # Check if file exists.
then
echo "$date : $FSTABCLONE does not exist and has not been copied." >>$LOG
else
rm $DESTINATION$FSTAB
cp -Rp $FSTABCLONE "$DESTINATION$FSTAB"
echo "$date : /etc/fstab corrected for the clone." >>$LOG
fi
# After cloning ac opy of grub needs to be removed
rm -rf $FOLDERTOREMOVE
echo "$date : grub has been cleaned up for the clone." >>$LOG
echo "$date : " >>$LOG
echo "$date : System cloning is complete." >>$LOG
echo "$date : " >>$LOG
exit 0
##############################################################################
Here are the /etc/fstab and /etc/fstabClone files, respectively.
##############################################################################
#
# /etc/fstab: static file system information
#
# <file system> <dir> <type> <options> <dump> <pass>
tmpfs /tmp tmpfs nodev,nosuid 0 0
#
LABEL=htpcHome /home ext4 defaults 0 1
LABEL=ssdRoot / ext4 defaults 0 1
LABEL=ssdRootClone /mnt/ssdRootClone ext4 defaults 0 1
LABEL=slackRoot /mnt/slackware ext4 defaults 0 1
LABEL=grubPartition /boot/grub ext4 defaults 0 1
#LABEL=ssdSwap swap swap defaults 0 0
/dev/sda2 swap swap defaults 0 0
LABEL=mythGlenelg /home/david/MythTV/Glenelg xfs defaults,noatime,nodiratime,nosuid,nodev,allocsize=64m 0 1
LABEL=mythSturt /home/david/MythTV/Sturt xfs defaults,noatime,nodiratime,nosuid,nodev,allocsize=64m 0 1
# NFS client
#david-desktop:/ /mnt nfs4 rw,hard,intr,bg 0 0
#david-desktop:/music /home/david/Music nfs4 rw,hard,intr,bg 0 0
#david-desktop:/movies /home/david/Movies nfs4 rw,hard,intr,bg 0 0
# Samba
//david-desktop/movies /home/david/Movies cifs noatime,nodiratime,bg,username=david,password=david 0 0
//david-desktop/music /home/david/Music cifs noatime,nodiratime,bg,username=david,password=david 0 0
//david-desktop/tvseries /home/david/TVseries cifs noatime,nodiratime,bg,username=david,password=david 0 0
It requires my root /etc/fstab plus a "clone-version" /etc/fstabClone (see below)
It requires folders /mnt/ssdRootClone on the original and /mnt/ssdRoot on the Clone.
I run it as root.
##############################################################################
#!/bin/bash
# fileinfo.sh
LOG="/var/log/cloneArch.log"
date=`date "+%a %b %e %H:%M:%S %Y"`
DESTINATION="/mnt/ssdRootClone"
#DESTINATION="/home/david/Clone"
FSTAB="/etc/fstab"
FSTABCLONE="/etc/fstabClone"
FILES="/bin
/boot
/dev
/etc
/lib
/lib64
/opt
/root
/run
/sbin
/srv
/tmp
/usr
/var"
FOLDERTOREMOVE="$DESTINATION/boot/grub/grub"
echo "$date : " >>$LOG
echo "$date : System is being cloned." >>$LOG
echo "$date : Clone mounted at $DESTINATION" >>$LOG
echo "$date : " >>$LOG
# Clear the variable directpries from the destination first
#rm -rf $DESTINATION/tmp
#rm -rf $DESTINATION/var
for file in $FILES
do
if [ ! -e "$file" ] # Check if file exists.
then
echo "$date : $file does not exist and has not been cloned." >>$LOG
else
# Clone the system here
echo "$date : $file is next." >>$LOG
# rsync options used
#
# -a, --archive
# This is equivalent to -rlptgoD. It is a quick way of saying you
# want recursion and want to preserve almost everything (with -H
# being a notable omission). The only exception to the above
# equivalence is when --files-from is specified, in which case -r
# is not implied.
#
# Note that -a does not preserve hardlinks, because finding multiply
# linked files is expensive. You must separately specify -H.
#
# -u, --update
# This forces rsync to skip any files which exist on the destination
# and have a modified time that is newer than the source file.
# (If an existing destination file has a modification time equal to
# the source file's, it will be updated if the sizes are different.)
#
# Note that this does not affect the copying of symlinks or other
# special files. Also, a difference of file format between the
# sender and receiver is always considered to be important enough
# for an update, no matter what date is on the objects. In other
# words, if the source has a directory where the destination has a
# file, the transfer would occur regardless of the timestamps.
#
# This option is a transfer rule, not an exclude, so it doesn't
# affect the data that goes into the file-lists, and thus it
# doesn't affect deletions. It just limits the files that the
# receiver requests to be transferred.
#
# -H, --hard-links
# This tells rsync to look for hard-linked files in the source and
# link together the corresponding files on the destination. With-
# out this option, hard-linked files in the source are treated as
# though they were separate files.
#
# This option does NOT necessarily ensure that the pattern of hard
# links on the destination exactly matches that on the source.
# Cases in which the destination may end up with extra hard links
# include the following:
#
#
# o If the destination contains extraneous hard-links (more
# linking than what is present in the source file list),
# the copying algorithm will not break them explicitly.
# However, if one or more of the paths have content differ-
# ences, the normal file-update process will break those
# extra links (unless you are using the --inplace option).
#
# o If you specify a --link-dest directory that contains hard
# links, the linking of the destination files against the
# --link-dest files can cause some paths in the destination
# to become linked together due to the --link-dest associa-
# tions.
#
#
# Note that rsync can only detect hard links between files that
# are inside the transfer set. If rsync updates a file that has
# extra hard-link connections to files outside the transfer, that
# linkage will be broken. If you are tempted to use the --inplace
# option to avoid this breakage, be very careful that you know how
# your files are being updated so that you are certain that no
# unintended changes happen due to lingering hard links (and see
# the --inplace option for more caveats).
#
# If incremental recursion is active (see --recursive), rsync may
# transfer a missing hard-linked file before it finds that another
# link for that contents exists elsewhere in the hierarchy. This
# does not affect the accuracy of the transfer (i.e. which files
# are hard-linked together), just its efficiency (i.e. copying the
# data for a new, early copy of a hard-linked file that could have
# been found later in the transfer in another member of the
# hard-linked set of files). One way to avoid this inefficiency
# is to disable incremental recursion using the --no-inc-recursive
# option.
rsync -aqHu --delete --stats --log-file=$LOG --log-file-format="%n" $file $DESTINATION
# make use of "$ du" command
# du -s $file | awk '{ print $2 "is " $1 }'
echo "$date : $file successfully cloned." >>$LOG
fi
done
# After cloning, fstab is going to mount the wrong partition
# Use the fstabClone for the corrected mounts.
if [ ! -e "$FSTABCLONE" ] # Check if file exists.
then
echo "$date : $FSTABCLONE does not exist and has not been copied." >>$LOG
else
rm $DESTINATION$FSTAB
cp -Rp $FSTABCLONE "$DESTINATION$FSTAB"
echo "$date : /etc/fstab corrected for the clone." >>$LOG
fi
# After cloning ac opy of grub needs to be removed
rm -rf $FOLDERTOREMOVE
echo "$date : grub has been cleaned up for the clone." >>$LOG
echo "$date : " >>$LOG
echo "$date : System cloning is complete." >>$LOG
echo "$date : " >>$LOG
exit 0
##############################################################################
Here are the /etc/fstab and /etc/fstabClone files, respectively.
##############################################################################
#
# /etc/fstab: static file system information
#
# <file system> <dir> <type> <options> <dump> <pass>
tmpfs /tmp tmpfs nodev,nosuid 0 0
#
LABEL=htpcHome /home ext4 defaults 0 1
LABEL=ssdRoot / ext4 defaults 0 1
LABEL=ssdRootClone /mnt/ssdRootClone ext4 defaults 0 1
LABEL=slackRoot /mnt/slackware ext4 defaults 0 1
LABEL=grubPartition /boot/grub ext4 defaults 0 1
#LABEL=ssdSwap swap swap defaults 0 0
/dev/sda2 swap swap defaults 0 0
LABEL=mythGlenelg /home/david/MythTV/Glenelg xfs defaults,noatime,nodiratime,nosuid,nodev,allocsize=64m 0 1
LABEL=mythSturt /home/david/MythTV/Sturt xfs defaults,noatime,nodiratime,nosuid,nodev,allocsize=64m 0 1
# NFS client
#david-desktop:/ /mnt nfs4 rw,hard,intr,bg 0 0
#david-desktop:/music /home/david/Music nfs4 rw,hard,intr,bg 0 0
#david-desktop:/movies /home/david/Movies nfs4 rw,hard,intr,bg 0 0
# Samba
//david-desktop/movies /home/david/Movies cifs noatime,nodiratime,bg,username=david,password=david 0 0
//david-desktop/music /home/david/Music cifs noatime,nodiratime,bg,username=david,password=david 0 0
//david-desktop/tvseries /home/david/TVseries cifs noatime,nodiratime,bg,username=david,password=david 0 0
##############################################################################
and
##############################################################################
#
# /etc/fstab: static file system information
#
# <file system> <dir> <type> <options> <dump> <pass>
tmpfs /tmp tmpfs nodev,nosuid 0 0
#
LABEL=htpcHome /home ext4 defaults 0 1
LABEL=ssdRoot /mnt/ssdRoot ext4 defaults 0 1
LABEL=ssdRootClone / ext4 defaults 0 1
LABEL=slackRoot /mnt/slackware ext4 defaults 0 1
LABEL=grubPartition /boot/grub ext4 defaults 0 1
#LABEL=ssdSwap swap swap defaults 0 0
/dev/sda2 swap swap defaults 0 0
LABEL=mythGlenelg /home/david/MythTV/Glenelg xfs defaults 0 1
LABEL=mythSturt /home/david/MythTV/Sturt xfs defaults 0 1
# NFS client
#david-desktop:/ /mnt nfs4 rw,hard,intr,bg 0 0
#david-desktop:/music /home/david/Music nfs4 rw,hard,intr,bg 0 0
#david-desktop:/movies /home/david/Movies nfs4 rw,hard,intr,bg 0 0
# Samba
//david-desktop/movies /home/david/Movies cifs noatime,bg,username=david,password=david 0 0
//david-desktop/music /home/david/Music cifs noatime,bg,username=david,password=david 0 0
//david-desktop/tvseries /home/david/TVseries cifs noatime,bg,username=david,password=david 0 0
##############################################################################
Monday, March 12, 2012
High quality user job transcode script for MythTV using Handbrake
A high quality user job script for MythTV that transcodes a recording to .mkv format and gives the resulting filename a human readable name.
#!/usr/bin/perl -w
# ============================================================================
# = NAME
# x264_transcode_high.pl
#
# = PURPOSE
# Convert mpeg2 file from myth to h264 with aac audio.
#
# = USAGE
my $usage = 'Usage:
x264_transcode_high.pl -j %JOBID%
x264_transcode_high.pl -f %FILE%
';
# ============================================================================
use strict;
use MythTV;
use XML::Simple;
# What file are we copying/transcoding?
my $file = '';
my $jobid = -1;
# do nothing?
my $noexec = 0;
# extra console output?
my $DEBUG = 1;
# some globals
my ($chanid, $command, $query, $ref, $starttime, $showtitle, $episodetitle);
my ($seasonnumber, $episodenumber, $episodedetails);
my ($newfilename, $newstarttime);
my $xmlparser = new XML::Simple;
my $xmlstring;
# globals for stream and resolution mapping
my ($output, $videostream, $audiostreamsurround, $audiostreamstereo, $framerate);
# transcode options
my $videocodec = "x264";
my $videoquality = "22"; # target quality
my $videobitrate = "1500k"; # target bitrate - not used if using videoquality
my $audiostream = 1; # default audio channel
my $audiocodec = "copy:ac3";
my $audiobitrate = "256";
my $audiochannels = "auto";
my $audiosamplerate = "Auto";
my $audiodrc = "1.0";
my $ftype = "mkv";
my $detelecine = "--detelecine";
my $decomb = "--decomb";
my $looseanamorphic = "--loose-anamorphic";
my $chapters = "-m";
# x264 options
my $badapt = "b-adapt=2";
my $rclookahead = "rc-lookahead=50";
my $x264options = "$badapt:$rclookahead";
# ref=2:bframes=2:subme=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0
my $mt = '';
my $db = '';
sub Reconnect()
{
$mt = new MythTV();
$db = $mt->{'dbh'};
}
# ============================================================================
sub Die($)
{
print STDERR "@_\n";
exit -1;
}
# ============================================================================
# Parse command-line arguments, check there is something to do:
#
if ( ! @ARGV )
{ Die "$usage" }
Reconnect;
while ( @ARGV && $ARGV[0] =~ m/^-/ )
{
my $arg = shift @ARGV;
if ( $arg eq '-d' || $arg eq '--debug' )
{ $DEBUG = 1 }
elsif ( $arg eq '-n' || $arg eq '--noaction' )
{ $noexec = 1 }
elsif ( $arg eq '-j' || $arg eq '--jobid' )
{ $jobid = shift @ARGV }
elsif ( $arg eq '-f' || $arg eq '--file' )
{ $file = shift @ARGV }
else
{
unshift @ARGV, $arg;
last;
}
}
if ( ! $file && $jobid == -1 )
{
Die "No file or job specified. $usage";
}
# ============================================================================
# If we were supplied a jobid, lookup chanid
# and starttime so that we can find the filename
#
if ( $jobid != -1 )
{
$query = $db->prepare("SELECT chanid, starttime " .
"FROM jobqueue WHERE id=$jobid;");
$query->execute || Die "Unable to query jobqueue table";
$ref = $query->fetchrow_hashref;
$chanid = $ref->{'chanid'};
$starttime = $ref->{'starttime'};
$query->finish;
if ( ! $chanid || ! $starttime )
{ Die "Cannot find details for job $jobid" }
$query = $db->prepare("SELECT basename FROM recorded " .
"WHERE chanid=$chanid AND starttime='$starttime';");
$query->execute || Die "Unable to query recorded table";
($file) = $query->fetchrow_array;
$query->finish;
if ( ! $file )
{ Die "Cannot find recording for chan $chanid, starttime $starttime" }
if ( $DEBUG )
{
print "Job $jobid refers to recording chanid=$chanid,",
" starttime=$starttime\n"
}
}
else
{
if ( $file =~ m/(\d+)_(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/ )
{ $chanid = $1, $starttime = "$2-$3-$4 $5:$6:$7" }
else
{
print "File $file has a strange name. Searching in recorded table\n";
$query = $db->prepare("SELECT chanid, starttime " .
"FROM recorded WHERE basename='$file';");
$query->execute || Die "Unable to query recorded table";
($chanid,$starttime) = $query->fetchrow_array;
$query->finish;
if ( ! $chanid || ! $starttime )
{ Die "Cannot find details for filename $file" }
}
}
# A commonly used SQL row selector:
my $whereChanAndStarttime = "WHERE chanid=$chanid AND starttime='$starttime'";
# ============================================================================
# Find the directory that contains the recordings, check the file exists
#
my $dir = undef;
my $dirs = $mt->{'video_dirs'};
foreach my $d ( @$dirs )
{
if ( ! -e $d )
{ Die "Cannot find directory $dir that contains recordings" }
if ( -e "$d/$file" )
{
$dir = $d;
last
}
else
{ print "$d/$file does not exist\n" }
}
if ( ! $dir )
{ Die "Cannot find recording" }
# ============================================================================
# Do you want to implement the deinterlace feature?
#my $dowedeinterlace = " ";
# ============================================================================
# Use ffmpeg to find if we need to deinterlace
my $deinterlace = " ";
#if ( $dowedeinterlace == '1')
# {
# $command = "ffmpeg -i $dir/$file ";
# open(FF_info, "$command 2>&1 |");
# while ( defined(my $line = ) ) {
# chomp($line);
# if ( $line =~ /^\s*Stream.*#(\S\.\S).*:\sVideo.*\s(\S*)\stbr/ )
# {
# $framerate = $2;
# next;
# }
# }
# if ( $framerate <= 30.0 ) { $deinterlace = "--deinterlace" } elsif ( $framerate > 30 && $framerate <= 60 ) { $deinterlace = "" }
#}
# ============================================================================
# First, generate a new filename,
#
$query = $db->prepare("SELECT title FROM recorded $whereChanAndStarttime;");
$query->execute || Die "Unable to query recorded table";
$showtitle = $query->fetchrow_array;
$query->finish;
$query = $db->prepare("SELECT subtitle FROM recorded $whereChanAndStarttime;");
$query->execute || Die "Unable to query recorded table";
$episodetitle = $query->fetchrow_array;
$query->finish;
if ( $episodetitle ne "" )
{
$seasonnumber = "";
$episodenumber = "";
$xmlstring = `/usr/share/mythtv/metadata/Television/ttvdb.py -N "$showtitle" "$episodetitle"`;
if ( $xmlstring ne "" ) {
$episodedetails =$xmlparser->XMLin($xmlstring);
$seasonnumber = $episodedetails->{item}->{season};
$episodenumber = $episodedetails->{item}->{episode};
}
}
my ($year,$month,$day,$hour,$mins,$secs) = split m/[- :]/, $starttime;
my $oldShortTime = sprintf "%04d%02d%02d",
$year, $month, $day;
my $iter = 0;
do {
if ( $episodetitle eq "" || $seasonnumber eq "" || $episodenumber eq "" )
{
$newfilename = sprintf "%s_%s.%s.%s", $showtitle, $month, $day, $year;
} else {
$newfilename = sprintf "%s_S%0sE%0s_%s", $showtitle, $seasonnumber, $episodenumber, $episodetitle;
}
$newfilename =~ s/\;/ AND /g;
$newfilename =~ s/\&/ AND /g;
$newfilename =~ s/\s+/ /g;
$newfilename =~ s/\s/_/g;
$newfilename =~ s/:/_/g;
$newfilename =~ s/__/_/g;
$newfilename =~ s/\(//g;
$newfilename =~ s/\)//g;
$newfilename =~ s/'//g;
$newfilename =~ s/\!//g;
$newfilename =~ s/\///g;
if ( $iter != "0" )
{ $newfilename = sprintf "%s_%d%s", $newfilename, $iter, ".mkv" } else { $newfilename = sprintf "%s%s", $newfilename, ".mkv" }
$iter ++;
$secs = $secs + $iter;
$newstarttime = sprintf "%04d-%02d-%02d %02d:%02d:%02d",
$year, $month, $day, $hour, $mins, $secs;
} while ( -e "$dir/$newfilename" );
$DEBUG && print "$dir/$newfilename seems unique\n";
# ============================================================================
# Third, do the transcode
#
# $audiochannels = 6;
# $audiostream = $audiostreamsurround;
# if ( $audiostreamsurround eq "" )
# {
# $audiochannels = 2;
# $audiostream = $audiostreamstereo;
# }
$command = "/usr/bin/HandBrakeCLI -i $file";
$command = "$command -o $newfilename";
$command = "$command -e $videocodec";
$command = "$command -q $videoquality";
$command = "$command -a $audiostream";
$command = "$command -E $audiocodec";
$command = "$command -B $audiobitrate";
$command = "$command -6 $audiochannels";
$command = "$command -R $audiosamplerate";
$command = "$command -D $audiodrc";
$command = "$command -f $ftype";
$command = "$command $detelecine";
$command = "$command $decomb";
$command = "$command $looseanamorphic";
$command = "$command $chapters";
$command = "$command $deinterlace";
$command = "$command -x $x264options";
$DEBUG && print "Executing: $command\n";
chdir $dir;
system $command;
if ( ! -e "$dir/$newfilename" )
{ Die "Transcode failed\n" }
# ============================================================================
# Last, copy the existing recorded details with the new file name.
#
Reconnect;
$query = $db->prepare("SELECT * FROM recorded $whereChanAndStarttime;");
$query->execute || Die "Unable to query recorded table";
$ref = $query->fetchrow_hashref;
$query->finish;
$ref->{'starttime'} = $newstarttime;
$ref->{'basename'} = $newfilename;
if ( $DEBUG && ! $noexec )
{
print 'Old file size = ' . (-s "$dir/$file") . "\n";
print 'New file size = ' . (-s "$dir/$newfilename") . "\n";
}
$ref->{'filesize'} = -s "$dir/$newfilename";
my $extra = 'Copy';
#
# The new recording file has no cutlist, so we don't insert that field
#
my @recKeys = grep(!/^cutlist$/, keys %$ref);
#
# Build up the SQL insert command:
#
$command = 'INSERT INTO recorded (' . join(',', @recKeys) . ') VALUES ("';
foreach my $key ( @recKeys )
{
if (defined $ref->{$key})
{ $command .= quotemeta($ref->{$key}) . '","' }
else
{ chop $command; $command .= 'NULL,"' }
}
chop $command; chop $command; # remove trailing comma quote
$command .= ');';
if ( $DEBUG || $noexec )
{ print "# $command\n" }
if ( ! $noexec )
{ $db->do($command) || Die "Couldn't create new recording's record, but transcoded file exists $newfilename\n" }
# Delete the old recording, keeping the new transcoded recording
if ( -e "$dir/$newfilename" )
{ $command = 'DELETE from recorded ' . join(',', $whereChanAndStarttime) . '; '; # Build up the SQL delete command:
$db->do($command); # remove the mysql entry for the recording
my $filepng = $file . join(',','.png'); # Create the file png filename
unlink($file); # remove the original file
unlink($filepng); # remove the file's png
}
# ============================================================================
$db->disconnect;
1;
Normal Transcode user job script for MythTV using Handbrake
This is a script that uses Handbrake and can be run from a User Job to transcode a recording to .mkv giving the resulting file a human readable filename.
#!/usr/bin/perl -w
# ============================================================================
# = NAME
# x264_transcode_high.pl
#
# = PURPOSE
# Convert mpeg2 file from myth to h264 with aac audio.
#
# = USAGE
my $usage = 'Usage:
x264_transcode_normal.pl -j %JOBID%
x264_transcode_normal.pl -f %FILE%
';
# ============================================================================
use strict;
use MythTV;
use XML::Simple;
# What file are we copying/transcoding?
my $file = '';
my $jobid = -1;
# do nothing?
my $noexec = 0;
# extra console output?
my $DEBUG = 1;
# some globals
my ($chanid, $command, $query, $ref, $starttime, $showtitle, $episodetitle);
my ($seasonnumber, $episodenumber, $episodedetails);
my ($newfilename, $newstarttime);
my $xmlparser = new XML::Simple;
my $xmlstring;
# globals for stream and resolution mapping
my ($output, $videostream, $audiostreamsurround, $audiostreamstereo, $framerate);
# transcode options
my $videocodec = "x264";
my $videoquality = "22"; # target quality
my $audiostream = 1; # default audio channel
my $audiocodec = "copy:ac3";
my $audiobitrate = "160";
my $audiochannels = "auto";
my $audiosamplerate = "Auto";
my $audiodrc = "0.0";
my $ftype = "mkv";
my $anamorphic = "--strict-anamorphic";
my $chapters = "-m";
my $deinterlace = "--deinterlace";
# long word options - type them here
my $wordoptions = "$anamorphic";
# x264 options
my $refoption = "ref=2";
my $bframeoption = "bframes=2";
my $submeoption = "subme=6";
my $mixedrefsoption = "mixed-refs=0";
my $weightboption = "weightb=0";
my $eightbyeightoption = "8x8dct=0";
my $trellisoption = "trellis=0";
my $x264options = "$refoption:$bframeoption:$submeoption:$mixedrefsoption:$weightboption:$eightbyeightoption:$trellisoption";
my $mt = '';
my $db = '';
sub Reconnect()
{
$mt = new MythTV();
$db = $mt->{'dbh'};
}
# ============================================================================
sub Die($)
{
print STDERR "@_\n";
exit -1;
}
# ============================================================================
# Parse command-line arguments, check there is something to do:
#
if ( ! @ARGV )
{ Die "$usage" }
Reconnect;
while ( @ARGV && $ARGV[0] =~ m/^-/ )
{
my $arg = shift @ARGV;
if ( $arg eq '-d' || $arg eq '--debug' )
{ $DEBUG = 1 }
elsif ( $arg eq '-n' || $arg eq '--noaction' )
{ $noexec = 1 }
elsif ( $arg eq '-j' || $arg eq '--jobid' )
{ $jobid = shift @ARGV }
elsif ( $arg eq '-f' || $arg eq '--file' )
{ $file = shift @ARGV }
else
{
unshift @ARGV, $arg;
last;
}
}
if ( ! $file && $jobid == -1 )
{
Die "No file or job specified. $usage";
}
# ============================================================================
# If we were supplied a jobid, lookup chanid
# and starttime so that we can find the filename
#
if ( $jobid != -1 )
{
$query = $db->prepare("SELECT chanid, starttime " .
"FROM jobqueue WHERE id=$jobid;");
$query->execute || Die "Unable to query jobqueue table";
$ref = $query->fetchrow_hashref;
$chanid = $ref->{'chanid'};
$starttime = $ref->{'starttime'};
$query->finish;
if ( ! $chanid || ! $starttime )
{ Die "Cannot find details for job $jobid" }
$query = $db->prepare("SELECT basename FROM recorded " .
"WHERE chanid=$chanid AND starttime='$starttime';");
$query->execute || Die "Unable to query recorded table";
($file) = $query->fetchrow_array;
$query->finish;
if ( ! $file )
{ Die "Cannot find recording for chan $chanid, starttime $starttime" }
if ( $DEBUG )
{
print "Job $jobid refers to recording chanid=$chanid,",
" starttime=$starttime\n"
}
}
else
{
if ( $file =~ m/(\d+)_(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/ )
{ $chanid = $1, $starttime = "$2-$3-$4 $5:$6:$7" }
else
{
print "File $file has a strange name. Searching in recorded table\n";
$query = $db->prepare("SELECT chanid, starttime " .
"FROM recorded WHERE basename='$file';");
$query->execute || Die "Unable to query recorded table";
($chanid,$starttime) = $query->fetchrow_array;
$query->finish;
if ( ! $chanid || ! $starttime )
{ Die "Cannot find details for filename $file" }
}
}
# A commonly used SQL row selector:
my $whereChanAndStarttime = "WHERE chanid=$chanid AND starttime='$starttime'";
# ============================================================================
# Find the directory that contains the recordings, check the file exists
#
my $dir = undef;
my $dirs = $mt->{'video_dirs'};
foreach my $d ( @$dirs )
{
if ( ! -e $d )
{ Die "Cannot find directory $dir that contains recordings" }
if ( -e "$d/$file" )
{
$dir = $d;
last
}
else
{ print "$d/$file does not exist\n" }
}
if ( ! $dir )
{ Die "Cannot find recording" }
# ============================================================================
# Do you want to implement the deinterlace feature?
my $dowedeinterlace = "false";
# ============================================================================
# Use ffmpeg to find if we need to deinterlace
# my $deinterlace = " ";
if ( $dowedeinterlace == "true")
{
$command = "ffmpeg -i $dir/$file ";
open(FF_info, "$command 2>&1 |");
while ( defined(my $line = ) ) {
chomp($line);
if ( $line =~ /^\s*Stream.*#(\S\.\S).*:\sVideo.*\s(\S*)\stbr/ )
{
$framerate = $2;
next;
}
}
if ( $framerate <= 30.0 ) { $deinterlace = "--deinterlace" } elsif ( $framerate > 30 && $framerate <= 60 ) { $deinterlace = "" }
}
# ============================================================================
# First, generate a new filename,
#
$query = $db->prepare("SELECT title FROM recorded $whereChanAndStarttime;");
$query->execute || Die "Unable to query recorded table";
$showtitle = $query->fetchrow_array;
$query->finish;
$query = $db->prepare("SELECT subtitle FROM recorded $whereChanAndStarttime;");
$query->execute || Die "Unable to query recorded table";
$episodetitle = $query->fetchrow_array;
$query->finish;
if ( $episodetitle ne "" )
{
$seasonnumber = "";
$episodenumber = "";
$xmlstring = `/usr/share/mythtv/metadata/Television/ttvdb.py -N "$showtitle" "$episodetitle"`;
if ( $xmlstring ne "" ) {
$episodedetails =$xmlparser->XMLin($xmlstring);
$seasonnumber = $episodedetails->{item}->{season};
$episodenumber = $episodedetails->{item}->{episode};
}
}
my ($year,$month,$day,$hour,$mins,$secs) = split m/[- :]/, $starttime;
my $oldShortTime = sprintf "%04d%02d%02d",
$year, $month, $day;
my $iter = 0;
do {
if ( $episodetitle eq "" || $seasonnumber eq "" || $episodenumber eq "" )
{
$newfilename = sprintf "%s_%s.%s.%s", $showtitle, $month, $day, $year;
} else {
$newfilename = sprintf "%s_S%0sE%0s_%s", $showtitle, $seasonnumber, $episodenumber, $episodetitle;
}
$newfilename =~ s/\;/ AND /g;
$newfilename =~ s/\&/ AND /g;
$newfilename =~ s/\s+/ /g;
$newfilename =~ s/\s/_/g;
$newfilename =~ s/:/_/g;
$newfilename =~ s/__/_/g;
$newfilename =~ s/\(//g;
$newfilename =~ s/\)//g;
$newfilename =~ s/'//g;
$newfilename =~ s/\!//g;
$newfilename =~ s/\///g;
if ( $iter != "0" )
{ $newfilename = sprintf "%s_%d%s", $newfilename, $iter, ".mkv" } else { $newfilename = sprintf "%s%s", $newfilename, ".mkv" }
$iter ++;
$secs = $secs + $iter;
$newstarttime = sprintf "%04d-%02d-%02d %02d:%02d:%02d",
$year, $month, $day, $hour, $mins, $secs;
} while ( -e "$dir/$newfilename" );
$DEBUG && print "$dir/$newfilename seems unique\n";
# ============================================================================
# Third, do the transcode
#
# $audiochannels = 6;
# $audiostream = $audiostreamsurround;
# if ( $audiostreamsurround eq "" )
# {
# $audiochannels = 2;
# $audiostream = $audiostreamstereo;
# }
$command = "/usr/bin/HandBrakeCLI -i $file";
$command = "$command -o $newfilename";
$command = "$command -e $videocodec";
$command = "$command -q $videoquality";
$command = "$command -a $audiostream";
$command = "$command -E $audiocodec";
$command = "$command -B $audiobitrate";
$command = "$command -6 $audiochannels";
$command = "$command -R $audiosamplerate";
$command = "$command -D $audiodrc";
$command = "$command -f $ftype";
$command = "$command $wordoptions";
$command = "$command $chapters";
$command = "$command $deinterlace";
$command = "$command -x $x264options";
$DEBUG && print "Executing: $command\n";
chdir $dir;
system $command;
if ( ! -e "$dir/$newfilename" )
{ Die "Transcode failed\n" }
# ============================================================================
# Last, copy the existing recorded details with the new file name.
#
Reconnect;
$query = $db->prepare("SELECT * FROM recorded $whereChanAndStarttime;");
$query->execute || Die "Unable to query recorded table";
$ref = $query->fetchrow_hashref;
$query->finish;
$ref->{'starttime'} = $newstarttime;
$ref->{'basename'} = $newfilename;
if ( $DEBUG && ! $noexec )
{
print 'Old file size = ' . (-s "$dir/$file") . "\n";
print 'New file size = ' . (-s "$dir/$newfilename") . "\n";
}
$ref->{'filesize'} = -s "$dir/$newfilename";
my $extra = 'Copy';
#
# The new recording file has no cutlist, so we don't insert that field
#
my @recKeys = grep(!/^cutlist$/, keys %$ref);
#
# Build up the SQL insert command:
#
$command = 'INSERT INTO recorded (' . join(',', @recKeys) . ') VALUES ("';
foreach my $key ( @recKeys )
{
if (defined $ref->{$key})
{ $command .= quotemeta($ref->{$key}) . '","' }
else
{ chop $command; $command .= 'NULL,"' }
}
chop $command; chop $command; # remove trailing comma quote
$command .= ');';
if ( $DEBUG || $noexec )
{ print "# $command\n" }
if ( ! $noexec )
{ $db->do($command) || Die "Couldn't create new recording's record, but transcoded file exists $newfilename\n" }
# Delete the old recording, keeping the new transcoded recording
if ( -e "$dir/$newfilename" )
{ $command = 'DELETE from recorded ' . join(',', $whereChanAndStarttime) . '; '; # Build up the SQL delete command:
$db->do($command); # remove the mysql entry for the recording
my $filepng = $file . join(',','.png'); # Create the file png filename
unlink($file); # remove the original file
unlink($filepng); # remove the file's png
}
# ============================================================================
$db->disconnect;
1;
Efficient Transcode script for MythTV using Handbrake
Efficient Transcode - transcodes to .mkv format, giving an improved human readable filename.
#!/usr/bin/perl -w
# ============================================================================
# = NAME
# x264_transcode_efficient.pl
#
# = PURPOSE
# Convert mpeg2 file from myth to h264 with aac audio.
#
# = USAGE
my $usage = 'Usage:
x264_transcode_efficient.pl -j %JOBID%
x264_transcode_efficient.pl -f %FILE%
';
# ============================================================================
use strict;
use MythTV;
use XML::Simple;
# What file are we copying/transcoding?
my $file = '';
my $jobid = -1;
# do nothing?
my $noexec = 0;
# extra console output?
my $DEBUG = 1;
# some globals
my ($chanid, $command, $query, $ref, $starttime, $showtitle, $episodetitle);
my ($seasonnumber, $episodenumber, $episodedetails);
my ($newfilename, $newstarttime);
my $xmlparser = new XML::Simple;
my $xmlstring;
# globals for stream and resolution mapping
my ($videostream, $audiostreamsurround, $audiostreamstereo, $framerate);
# Set your desired output directory
# my $outputdir = "/home/david/tmp";
# transcode options
my $videocodec = "x264";
my $videoquality = "24"; # target quality
my $audiostream = 1; # default audio channel
my $audiocodec = "copy:ac3";
my $audiobitrate = "160";
my $audiochannels = "auto";
my $audiosamplerate = "Auto";
my $audiodrc = "0.0";
my $ftype = "mkv";
my $anamorphic = "--strict-anamorphic";
my $detelecine = "--detelecine";
my $decomb = "--decomb";
my $deinterlace = "--deinterlace";
my $chapters = "-m";
# long word options - type them here
#
# my $wordoptions = "$anamorphic $decomb $detelecine $deinterlace";
my $wordoptions = "$anamorphic $deinterlace";
# x264 options
my $refoption = "ref=1";
my $bframeoption = "bframes=2";
my $submeoption = "subme=5";
my $mixedrefsoption = "mixed-refs=0";
my $weightboption = "weightb=0";
my $eightbyeightoption = "8x8dct=0";
my $trellisoption = "trellis=0";
my $entropyoption = "cabac=0";
my $partitionoption = "partitions=i4x4,i8x8";
my $motionoption = "me=dia";
my $x264options = "$refoption:$bframeoption:$submeoption:$mixedrefsoption:$weightboption:$eightbyeightoption:$trellisoption:$entropyoption:$partitionoption:$motionoption";
my $mt = '';
my $db = '';
sub Reconnect()
{
$mt = new MythTV();
$db = $mt->{'dbh'};
}
# ============================================================================
sub Die($)
{
print STDERR "@_\n";
exit -1;
}
# ============================================================================
# Parse command-line arguments, check there is something to do:
#
if ( ! @ARGV )
{ Die "$usage" }
Reconnect;
while ( @ARGV && $ARGV[0] =~ m/^-/ )
{
my $arg = shift @ARGV;
if ( $arg eq '-d' || $arg eq '--debug' )
{ $DEBUG = 1 }
elsif ( $arg eq '-n' || $arg eq '--noaction' )
{ $noexec = 1 }
elsif ( $arg eq '-j' || $arg eq '--jobid' )
{ $jobid = shift @ARGV }
elsif ( $arg eq '-f' || $arg eq '--file' )
{ $file = shift @ARGV }
else
{
unshift @ARGV, $arg;
last;
}
}
if ( ! $file && $jobid == -1 )
{
Die "No file or job specified. $usage";
}
# ============================================================================
# If we were supplied a jobid, lookup chanid
# and starttime so that we can find the filename
#
if ( $jobid != -1 )
{
$query = $db->prepare("SELECT chanid, starttime " .
"FROM jobqueue WHERE id=$jobid;");
$query->execute || Die "Unable to query jobqueue table";
$ref = $query->fetchrow_hashref;
$chanid = $ref->{'chanid'};
$starttime = $ref->{'starttime'};
$query->finish;
if ( ! $chanid || ! $starttime )
{ Die "Cannot find details for job $jobid" }
$query = $db->prepare("SELECT basename FROM recorded " .
"WHERE chanid=$chanid AND starttime='$starttime';");
$query->execute || Die "Unable to query recorded table";
($file) = $query->fetchrow_array;
$query->finish;
if ( ! $file )
{ Die "Cannot find recording for chan $chanid, starttime $starttime" }
if ( $DEBUG )
{
print "Job $jobid refers to recording chanid=$chanid,",
" starttime=$starttime\n"
}
}
else
{
if ( $file =~ m/(\d+)_(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/ )
{ $chanid = $1, $starttime = "$2-$3-$4 $5:$6:$7" }
else
{
print "File $file has a strange name. Searching in recorded table\n";
$query = $db->prepare("SELECT chanid, starttime " .
"FROM recorded WHERE basename='$file';");
$query->execute || Die "Unable to query recorded table";
($chanid,$starttime) = $query->fetchrow_array;
$query->finish;
if ( ! $chanid || ! $starttime )
{ Die "Cannot find details for filename $file" }
}
}
# A commonly used SQL row selector:
my $whereChanAndStarttime = "WHERE chanid=$chanid AND starttime='$starttime'";
# ============================================================================
# Find the directory that contains the recordings, check the file exists
#
my $dir = undef;
my $dirs = $mt->{'video_dirs'};
foreach my $d ( @$dirs )
{
if ( ! -e $d )
{ Die "Cannot find directory $dir that contains recordings" }
if ( -e "$d/$file" )
{
$dir = $d;
last
}
else
{ print "$d/$file does not exist\n" }
}
if ( ! $dir )
{ Die "Cannot find recording" }
# ============================================================================
# Do you want to implement the deinterlace feature?
#my $dowedeinterlace = "";
# ============================================================================
# Use ffmpeg to find if we need to deinterlace
#my $deinterlace = "";
#if ( $dowedeinterlace == '1')
# {
# $command = "ffmpeg -i $dir/$file ";
# open(FF_info, "$command 2>&1 |");
# while ( defined(my $line = ) ) {
# chomp($line);
# if ( $line =~ /^\s*Stream.*#(\S\.\S).*:\sVideo.*\s(\S*)\stbr/ )
# {
# $framerate = $2;
# next;
# }
# }
# if ( $framerate <= 30.0 ) { $deinterlace = "--deinterlace" } elsif ( $framerate > 30 && $framerate <= 60 ) { $deinterlace = "" }
#}
# ============================================================================
# First, generate a new filename,
#
$query = $db->prepare("SELECT title FROM recorded $whereChanAndStarttime;");
$query->execute || Die "Unable to query recorded table";
$showtitle = $query->fetchrow_array;
$query->finish;
$query = $db->prepare("SELECT subtitle FROM recorded $whereChanAndStarttime;");
$query->execute || Die "Unable to query recorded table";
$episodetitle = $query->fetchrow_array;
$query->finish;
if ( $episodetitle ne "" )
{
$seasonnumber = "";
$episodenumber = "";
$xmlstring = `/usr/share/mythtv/metadata/Television/ttvdb.py -N "$showtitle" "$episodetitle"`;
if ( $xmlstring ne "" ) {
$episodedetails =$xmlparser->XMLin($xmlstring);
$seasonnumber = $episodedetails->{item}->{season};
$episodenumber = $episodedetails->{item}->{episode};
}
}
my ($year,$month,$day,$hour,$mins,$secs) = split m/[- :]/, $starttime;
my $oldShortTime = sprintf "%04d%02d%02d",
$year, $month, $day;
my $iter = 0;
do {
if ( $episodetitle eq "" || $seasonnumber eq "" || $episodenumber eq "" )
{
$newfilename = sprintf "%s_%s.%s.%s", $showtitle, $month, $day, $year;
} else {
$newfilename = sprintf "%s_S%0sE%0s_%s", $showtitle, $seasonnumber, $episodenumber, $episodetitle;
}
$newfilename =~ s/\;/ AND /g;
$newfilename =~ s/\&/ AND /g;
$newfilename =~ s/\s+/ /g;
$newfilename =~ s/\s/_/g;
$newfilename =~ s/:/_/g;
$newfilename =~ s/__/_/g;
$newfilename =~ s/\(//g;
$newfilename =~ s/\)//g;
$newfilename =~ s/'//g;
$newfilename =~ s/\!//g;
$newfilename =~ s/\///g;
if ( $iter != "0" )
{ $newfilename = sprintf "%s_%d%s", $newfilename, $iter, ".mkv" } else { $newfilename = sprintf "%s%s", $newfilename, ".mkv" }
$iter ++;
$secs = $secs + $iter;
$newstarttime = sprintf "%04d-%02d-%02d %02d:%02d:%02d",
$year, $month, $day, $hour, $mins, $secs;
} while ( -e "$dir/$newfilename" );
$DEBUG && print "$dir/$newfilename seems unique\n";
# ============================================================================
# Third, do the transcode
#
# $audiochannels = 6;
# $audiostream = $audiostreamsurround;
# if ( $audiostreamsurround eq "" )
# {
# $audiochannels = 2;
# $audiostream = $audiostreamstereo;
# }
$command = "/usr/bin/HandBrakeCLI -i $file";
$command = "$command -o $newfilename";
$command = "$command -e $videocodec";
$command = "$command -q $videoquality";
$command = "$command -a $audiostream";
$command = "$command -E $audiocodec";
$command = "$command -B $audiobitrate";
$command = "$command -6 $audiochannels";
$command = "$command -R $audiosamplerate";
$command = "$command -D $audiodrc";
$command = "$command -f $ftype";
$command = "$command $wordoptions";
$command = "$command $chapters";
$command = "$command $deinterlace";
$command = "$command -x $x264options";
$DEBUG && print "Executing: $command\n";
chdir $dir;
system $command;
if ( ! -e "$dir/$newfilename" )
{ Die "Transcode failed\n" }
# ============================================================================
# Last, copy the existing recorded details with the new file name.
#
Reconnect;
$query = $db->prepare("SELECT * FROM recorded $whereChanAndStarttime;");
$query->execute || Die "Unable to query recorded table";
$ref = $query->fetchrow_hashref;
$query->finish;
$ref->{'starttime'} = $newstarttime;
$ref->{'basename'} = $newfilename;
if ( $DEBUG && ! $noexec )
{
print 'Old file size = ' . (-s "$dir/$file") . "\n";
print 'New file size = ' . (-s "$dir/$newfilename") . "\n";
}
$ref->{'filesize'} = -s "$dir/$newfilename";
my $extra = 'Copy';
#
# The new recording file has no cutlist, so we don't insert that field
#
my @recKeys = grep(!/^cutlist$/, keys %$ref);
#
# Build up the SQL insert command:
#
$command = 'INSERT INTO recorded (' . join(',', @recKeys) . ') VALUES ("';
foreach my $key ( @recKeys )
{
if (defined $ref->{$key})
{ $command .= quotemeta($ref->{$key}) . '","' }
else
{ chop $command; $command .= 'NULL,"' }
}
chop $command; chop $command; # remove trailing comma quote
$command .= ');';
if ( $DEBUG || $noexec )
{ print "# $command\n" }
if ( ! $noexec )
{ $db->do($command) || Die "Couldn't create new recording's record, but transcoded file exists $newfilename\n" }
# Delete the old recording, keeping the new transcoded recording
if ( -e "$dir/$newfilename" )
{ $command = 'DELETE from recorded ' . join(',', $whereChanAndStarttime) . '; '; # Build up the SQL delete command:
$db->do($command); # remove the mysql entry for the recording
my $filepng = $file . join(',','.png'); # Create the file png filename
unlink($file); # remove the original file
unlink($filepng); # remove the file's png
}
# ============================================================================
$db->disconnect;
1;
MythTV scripts used
mythbackup.sh (I don't use this one)
mythidle.pl - courtesy of Arkay @ pcmediacenter.com.au
(be careful if cutting and pasting this, due to narrow width of the printout, some lines may have carried over to a new line, when they should not have)
Pre-shutdown-check command: /home/david/scripts/mythidle.pl
setwakeup.sh
sudo sh -c "/home/david/scripts/setwakeup.sh $time"
shutdown.sh
sudo sh -c "/home/david/scripts/shutdown.sh"
#Dumps the mythconverg database - daily backup #Keeps the last 7 days #!/bin/sh LOG="/var/log/archmyth.log" DAY=`/bin/date +%u` DUMPFILE="~/.mythtv/mythbackup/mythdb_$DAY.sql" DATE=`date` echo "$DATE : Backuping up myth database to $DUMPFILE" >> $LOG /usr/bin/mysqldump -u mythtv -pmythtv mythconverg -c > $DUMPFILE DATE=`date` echo "$DATE : Backup completed." >> $LOG exit 0
mythidle.pl - courtesy of Arkay @ pcmediacenter.com.au
(be careful if cutting and pasting this, due to narrow width of the printout, some lines may have carried over to a new line, when they should not have)
Pre-shutdown-check command: /home/david/scripts/mythidle.pl
#!/usr/bin/perl -w ############################################################################################################################### ## Name: mythidle.pl ## ## Purpose: Checks to determine if the mythbackend server is idle and ready for shutdown. ## ## (C)opyright 2008 Arksoft. ## ## Author: Arkay ## ## Ver 1.0: 14-07-2008. Initial version. ## ############################################################################################################################### # Require and Use Clauses. ############################################################################################################################### use strict; #Keeps code neat. use Getopt::Std; #Getopt module for option preprocessing. use vars qw/ $opt_d $opt_h /; #Option Processing vars. use POSIX qw(strftime); #Time routine we need. ############################################################################################################################### # Prototype definitions ############################################################################################################################### sub logmsg(@); #Message logger so we can track what's been going on. sub process_opts(); #Option processing.. Nothing exiting for this script. sub do_command($); #Execute a shell command for lazy perl programmers :) sub check_hosts(); #Are any server dependant hosts currently up? sub check_procs(); #Check if the server is running anything that should keep us awake. sub check_myth(); #Check if mythbackend is busy doing anything. ############################################################################################################################### # Constant Definitions. ############################################################################################################################### my ($TRUE) = 1; my ($FALSE) = 0; ############################################################################################################################### # Global vars, paths, commands to call. ############################################################################################################################### my ($LOG) = "/var/log/archmyth.log"; #Log location. my ($LOGSIZE) = 1024; #Maximum log size in kbytes, self pruning. my ($DEBUG) = $FALSE; #Debugging default is off. my ($BASENAME) = $0; #How was the program called? my ($MYTHSTATUS)="/usr/bin/mythshutdown --status;echo \$\?"; #Command to query myth status my ($PING)="/bin/ping"; #Where is ping ############################################################################################################################### # These are the only 2 lines in this file that should be edited. # The first (@procs) is a list of processes that when running should keep the server awake. # The second (@HOSTS) lists hosts that, if active, prevents the server from sleeping. # To acertain the name of a process to see if it still running use ps -ef | grep -i# The names of the hosts listed below need to exist in your /etc/hosts file. You can check # that they are up with ping # Both lines consist of a comma separate list of quoted strings. i.e. #my (@PROCS)=("dpexpress","ktorrent","shepherd","altbinz"); #Stay awake if active. #my (@HOSTS)=("debs","htpc-lounge","quadarch"); #stay awake if any of these are up ############################################################################################################################### my (@PROCS)=("shepherd","xbmc","chromium","vlc","smplayer","HandBrakeCLI"); #stay awake? my (@HOSTS)=("myth-frontend"); #stay awake if any of these are up ############################################################################################################################### # The Mainline. ############################################################################################################################### MAIN: { my ($blocked)=$FALSE; process_opts(); logmsg "$BASENAME started : PID($$)"; SWITCH: #blocked { if (check_hosts() != $FALSE) #Check it any client hosts are up { $blocked=$TRUE; last; } if (check_procs() != $FALSE) #Check if any processes are blocking shutdown { $blocked=$TRUE; last; } if (check_myth() != $FALSE) #Check if myth is busy { $blocked=$TRUE; last; } $blocked=$FALSE; } if ($blocked == $TRUE) { logmsg "Mythbackend is not idle - blocking Shutdown."; } else { logmsg "Mythbackend is currently idle - Allowing Shutdown."; } logmsg "$BASENAME Completed."; logmsg " "; exit($blocked); } ############################################################################################################################### # check_procs() # Check if processes are running that should stop shutdown from occuring. ############################################################################################################################### sub check_procs() { my (@output); my ($proc); my ($command); my ($count)=0; my ($running)=$FALSE; logmsg "PROC - Checking active processes that block shutdown."; foreach $proc (@PROCS) { $command="ps -ef | grep $proc | grep -v grep |wc -l"; @output=do_command($command); if (@output) { $count=$output[0]; chomp ($count); } if ($count > 0) { logmsg "PROC - Found active process : $proc ($count running)."; $running=$TRUE; } } logmsg "PROC - No blocking processes currently running." if ($running) == $FALSE; return($running); } ############################################################################################################################### # check_myth() # Check if we have active samba connections. ############################################################################################################################### sub check_myth() { my (@output); my ($status)=69; my ($text)="Unknown"; logmsg "MYTH - Checking mythbackend status."; @output=do_command($MYTHSTATUS); if (@output) { $status=$output[0]; chomp($status); $text="Idle." if ($status) == 0; $text="Transcoding." if ($status) == 1; $text="Flagging Commercials." if ($status) == 2; $text="Grabbing EPG Data." if ($status) == 4; $text="Recording." if ($status) == 8; $text="Locked." if ($status) == 16; $text="Jobs running/pending." if ($status) == 32; $text="In a daily wakeup/shutdown period." if ($status) == 64; $text="Less than 15 minutes to next wakeup period." if ($status) == 128; $text="Setup is running." if ($status) == 255; logmsg "MYTH - Mythbackend status ($status) : $text"; } else { logmsg "MYTH - Failed to get mythbackend status."; } return($status); } ############################################################################################################################### # check_hosts() # Checkif we have active samba connections. ############################################################################################################################### sub check_hosts() { my ($line); my ($host); my (@output,@ping); my ($up)=$FALSE; my ($command); logmsg "HOSTS - Checking for active client hosts."; foreach $host (@HOSTS) { $command="$PING -c2 $host | grep received | awk '{print \$4}'"; @output=do_command($command); if ($output[0] != 0) { logmsg "HOSTS - Client host \"$host\" is still up."; $up=$TRUE; last; } else { logmsg "HOSTS - Client host \"$host\" is currently down."; } } logmsg "HOSTS - No active client hosts found." if ($up == $FALSE); return($up); } ############################################################################################################################### # logmsg # Little routine to write to the log file. # Rotates around $LOGSIZE bytes. ############################################################################################################################### sub logmsg(@) { my ($string)=@_; my $time=scalar localtime; my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks); my (@lines,$line); ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks)=stat("$LOG"); if (defined($size)) { $size=$size/1024; #size in kbyte if ($size >= $LOGSIZE) { unlink ("$LOG.old") if (-e("$LOG.old")); rename ($LOG,"$LOG.old"); } } print "$time : $string\n" if ($DEBUG==$TRUE); if (open (LOG,">>$LOG")) { if ($string =~ /\n/) { @lines=split(/\n/,$string); foreach $line (@lines) { print LOG "$time : $line\n"; } } else { print LOG "$time : $string\n"; } close (LOG); } else { print "Unable to open LOG $LOG : $!"; } } ############################################################################################################################### # process_opts() # Set Global option flags dependant on command line input. ############################################################################################################################### sub process_opts() { getopts('dh'); $DEBUG=$TRUE if ($opt_d); exit(usage(1)) if ($opt_h); } ############################################################################################################################### # usage() # Output Relevant Usage strings if incorrect opts are given. ############################################################################################################################### sub usage() { my($ucode)=@_; if ($ucode == 1) { print "Usage: $BASENAME [-dh]\n"; return(0); } } ############################################################################################################################### # sub do_command($) # use system call to execute command. Returns output of command in array. ############################################################################################################################### sub do_command($) { my ($command)=@_; my (@output); my ($exit_value)=0; logmsg "Executing $command" if ($DEBUG == $TRUE); @output=`$command`; $exit_value = $? >> 8; if ($exit_value != 0) { logmsg "Error executing $command : $!"; } return(@output); }
setwakeup.sh
sudo sh -c "/home/david/scripts/setwakeup.sh $time"
#!/bin/sh #$1 is the first argument to the script. It is the time in seconds since 1970 #this is defined in mythtv-setup with the time_t argument LOG="/var/log/archmyth.log" #Set the wakeup timers. echo 0 > /sys/class/rtc/rtc0/wakealarm #this clears your alarm. echo $1 > /sys/class/rtc/rtc0/wakealarm #this writes the alarm. date=`date "+%a %b %e %H:%M:%S %Y"` schedutc=`date -u -d @$1 +%F" "%T` sched=`date -d @$1 +%F" "%T` echo "$date : Next scheduled recording : $sched ($schedutc UTC)" >>$LOG #cat /proc/driver/rtc | head -4 >>$LOG
shutdown.sh
sudo sh -c "/home/david/scripts/shutdown.sh"
#!/bin/sh LOG="/var/log/archmyth.log" date=`date "+%a %b %e %H:%M:%S %Y"` echo "$date : System Shutting down." >>$LOG /sbin/shutdown -h now
Subscribe to:
Posts (Atom)