Created
August 2, 2012 11:30
-
-
Save produnis/3236414 to your computer and use it in GitHub Desktop.
MythTV
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl -w | |
### User-Job-Command: | |
### /path/to/copy_and_transcode.pl -f %FILE% -p autodetect | |
# ============================================================================ | |
# = NAME | |
# copy_and_transcode.pl | |
# | |
# = PURPOSE | |
# Copy a recording before transcoding, so the user can re-cut the original | |
# | |
# = USAGE | |
my $usage = 'Usage: | |
copy_and_transcode.pl -f %FILE% -p autodetect | |
copy_and_transcode.pl -j %JOBID% -p autodetect | |
copy_and_transcode.pl --file file [--debug] [--noaction] [transcode-arguments] | |
'; | |
# The first two forms would invoke this as a MythTV User Job | |
# | |
# = DESCRIPTION | |
# The exsisting mythtranscode system is designed for replacing a recording | |
# with a transcoded copy. There is a setting which causes the backend to | |
# keep the original file, but both the seektable and the cutlist are deleted. | |
# If you are using transcode to extract multiple clips from a recording, | |
# this is very inconvenient. | |
# | |
# This script transcodes a recording into a new recording, | |
# with a trivially different starttime. | |
# If the original recording had a cutlist, that should be honoured in the copy. | |
# | |
# = INSTALLATION | |
# Copy this script to a known location, and then add the command | |
# in mythtv-setup as a User Job (pg. 7 & 9 of General button) e.g. | |
# | |
# cp copy_and_transcode.pl /usr/local/bin | |
# UserJob1 /usr/local/bin/copy_and_transcode.pl -f %FILE% -p autodetect | |
# UserJobDesc1 Copy and Transcode | |
# | |
# = KNOWN BUGS | |
# | |
# = REVISION | |
# $Id: copy_and_transcode.pl 20349 2009-04-11 00:04:30Z xris $ | |
# | |
# = AUTHORS | |
# Nigel Pearson | |
# ============================================================================ | |
use strict; | |
use MythTV; | |
# 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); | |
my ($newfilename, $newstarttime); | |
my $mt = new MythTV(); | |
my $db = $mt->{'dbh'}; | |
# ============================================================================ | |
sub Die($) | |
{ | |
print STDERR "@_\n"; | |
exit -1; | |
} | |
# ============================================================================ | |
# Parse command-line arguments, check there is something to do: | |
# | |
if ( ! @ARGV ) | |
{ Die "$usage" } | |
while ( @ARGV && $ARGV[0] =~ m/^-/ ) | |
{ | |
my $arg = shift; | |
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 } | |
elsif ( $arg eq '-f' || $arg eq '--file' ) | |
{ $file = shift } | |
else | |
{ | |
unshift @ARGV, $arg; | |
last; | |
} | |
} | |
if ( ! $file && $jobid == -1 ) | |
{ | |
print "No file or job specified. $usage"; | |
exit; | |
} | |
if ( $noexec ) | |
{ print "NoExecute mode. No transcoding or SQL database changes.\n" } | |
# ============================================================================ | |
# 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; | |
#print "$d/$file exists\n"; | |
last | |
} | |
else | |
{ print "$d/$file does not exist\n" } | |
} | |
if ( ! $dir ) | |
{ Die "Cannot find recording" } | |
# ============================================================================ | |
# First, generate a new filename, | |
# by adding one second to the starttime until we get a unique one | |
# | |
my ($year,$month,$day,$hour,$mins,$secs) = split m/[- :]/, $starttime; | |
my $oldShortTime = sprintf "%04d%02d%02d%02d%02d%02d", | |
$year, $month, $day, $hour, $mins, $secs; | |
do | |
{ | |
$secs ++; | |
if ( $secs > 59 ) | |
{ $secs -= 60, $mins ++ } | |
if ( $mins > 59 ) | |
{ $mins -= 60, $hour ++ } | |
if ( $hour > 23 ) | |
{ Die "Cannot generate a new file" } | |
$newstarttime = sprintf "%04d-%02d-%02d %02d:%02d:%02d", | |
$year, $month, $day, $hour, $mins, $secs; | |
my $newShrtTm = sprintf "%04d%02d%02d%02d%02d%02d", | |
$year, $month, $day, $hour, $mins, $secs; | |
$newfilename = $file; | |
$newfilename =~ s/_$oldShortTime/_$newShrtTm/; | |
} while ( -e "$dir/$newfilename" ); | |
$DEBUG && print "$dir/$newfilename seems unique\n"; | |
# ============================================================================ | |
# Second, do the transcode, obeying the cutlist if there is one | |
# | |
$query = $db->prepare("SELECT cutlist FROM recorded $whereChanAndStarttime;"); | |
$query->execute || Die "Unable to query recorded table"; | |
my ($cutlist) = $query->fetchrow_array; | |
$ref = $query->fetchrow_hashref; | |
$query->finish; | |
$command = "mythtranscode -c $chanid -s '$starttime' -m --outfile $newfilename"; | |
if ($cutlist) | |
{ $command .= ' --honorcutlist' } | |
if ( @ARGV ) | |
{ $command .= ' ' . join(' ', @ARGV) } | |
if ( $DEBUG || $noexec ) | |
{ print "# $command\n" } | |
if ( ! $noexec ) | |
{ | |
chdir $dir; | |
system $command; | |
if ( ! -e "$dir/$newfilename" ) | |
{ Die "Transcode failed\n" } | |
# Insert the generated position map into the recorded markup table. | |
# File has a structure like this: | |
# | |
#Type: 9 | |
#0 14 | |
#12 380942 | |
# | |
open(MAP, "$newfilename.map") || Die "Cannot find position map file"; | |
my $type; | |
if ( <MAP> =~ m/^Type: (\d+)$/ ) | |
{ $type = $1 } | |
else | |
{ Die "Position map file is incomplete" } | |
while ( <MAP> ) | |
{ | |
if ( m/^(\d+) (\d+)$/ ) | |
{ | |
$command = "INSERT INTO recordedseek" . | |
" (chanid,starttime,mark,offset,type)" . | |
" VALUES ($chanid,'$newstarttime',$1,$2,$type);"; | |
# This outputs too many lines for normal debugging | |
#if ( $DEBUG || $noexec ) | |
#{ print "# $command\n" } | |
if ( ! $noexec ) | |
{ | |
$db->do($command) || | |
Die "Couldn't insert data into recordedmarkup" | |
} | |
} | |
else | |
{ Die "Position map file has bad data line" } | |
} | |
close MAP; | |
unlink "$newfilename.map" || Die "Cannot delete position map file"; | |
} | |
# ============================================================================ | |
# Last, copy the existing recorded details with the new file name. | |
# | |
$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'; | |
if ( $cutlist ) | |
{ $extra = 'Cut' } | |
if ( $ref->{'subtitle'} !~ m/$extra$/ ) | |
{ | |
if ( $ref->{'subtitle'} ) | |
{ $ref->{'subtitle'} .= " - $extra" } | |
else | |
{ $ref->{'subtitle'} = $extra } | |
} | |
# | |
# 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" } | |
# ============================================================================ | |
$db->disconnect; | |
1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# | |
### User-Job-Command: | |
### /path/to/mythscp.py %CHANID% %STARTTIME% | |
import os, sys | |
import re | |
import dbus | |
import logging | |
import time | |
import pexpect | |
#------------------------------------------ | |
# | |
# | |
log_path = "/var/log/mythtv/mythscp.log" | |
chanid = sys.argv[1] | |
starttime = sys.argv[2] | |
# | |
############### FUNKTIONEN ------------------------------ | |
#----------- Zeitstempel erzeugen --------------------------- | |
def TimeStamp(): | |
stamp = time.strftime("%Y%m%d", time.localtime()) | |
return(stamp) | |
#----------------------------------------------------------- | |
#------- Log-File vorbereiten --------------------------- | |
# mehr Infos unter http://docs.python.org/library/logging.html | |
logging.basicConfig(filename=log_path, | |
level=logging.INFO, | |
format="%(asctime)s - %(levelname)s: %(message)s") | |
logger =logging.getLogger("") | |
logger.setLevel(logging.DEBUG) | |
ch = logging.StreamHandler() | |
ch.setLevel(logging.DEBUG) | |
formatter = logging.Formatter("%(asctime)s - %(levelname)s: %(message)s") | |
ch.setFormatter(formatter) | |
logger.addHandler(ch) | |
#--------------------------------------------------------- | |
# | |
# | |
######### HIER GEHTZ LOS --------------------------------- | |
logger.info("[%s]: Skript gestartet" % (TimeStamp())) | |
#logger.debug("Debugmeldung") | |
#logger.warning("Warnmeldung") | |
#os.system('enter your bash command here') | |
befehl = "/usr/share/doc/mythtv-backend/contrib/user_jobs/mythlink.pl --link /media/MYTH/tmp --chanid %s --starttime %s --format '%%Y%%m%%d%%H%%i%%s-%%c-%%T-%%S'" % (chanid,starttime) | |
os.system(befehl) | |
#--- Hole Datum, da die Videodatei so anfaengt | |
stamp = TimeStamp(); | |
myvideo = "%s-%s" % (starttime,chanid) | |
befehl = "/bin/bash -c 'scp /media/MYTH/tmp/%s* [email protected]:Downloads/'" % (myvideo) | |
#befehl = "scp [email protected]:/hdd/movie/%s* /home/produnis/Downloads/" % ("10-12-19") | |
logger.info("Dateien starten mit %s" % (stamp)) | |
logger.info("Verwende Befehl %s" % (befehl)) | |
# | |
# | |
child = pexpect.spawn (befehl) | |
#child.expect ('.*yes*') | |
#child.sendline ('yes') | |
child.expect ('.*password:*') | |
child.sendline ('hansch') | |
child.expect(pexpect.EOF, timeout=7200) | |
#print str(child) # Debugging | |
#print "Ende" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
##### Commercial Remover Script for MythTV, updated 5/14/12 | |
### | |
## Version Changes to mythutil and mythcommflag tools under MythTV 0.25 | |
## necessitate different commands within the script. (Under MythTV < 0.25 you could | |
## just point mythcommflag at the recordings in the file system and get the job done, now | |
## under MythTV 0.25 you have to use mythutil to generate the cutlist and mythcommflag to | |
## flag commercials, AND point both at recordings based on %CHANID% and %STARTTIME%. Under | |
## MythTV 0.25 mythtranscode can also be pointed at %CHANID% and %STARTTIME% but since it | |
## currently supports the older infile /outfile method as well (and I prefer how this | |
## script creates old/new files, it is the method used. | |
## | |
## Since this script requires the User Job to pass additional arguments under MythTV 0.25, | |
## use following User Job syntax for userjobs under all versions: | |
## | |
## 'commercialremover.sh %DIR% %FILE% %CHANID% %STARTTIME%' | |
## | |
## Credits: Zwhite, Ricks03, Waxrat @ www.mythtv.org/wiki | |
### | |
##### | |
VIDEODIR=$1 #MythTV-024 %DIR% | |
FILENAME=$2 #MythTV-024 %FILE% | |
CHAN=$3 #REQUIRED FOR MythTV-025 %CHANID% | |
START=$4 #REQUIRED FOR MythTV-025 %STARTTIME% | |
# Sanity checking, to make sure everything is in order. Modified to check $CHAN and $START for MythTV 0.25 Support | |
if [ -z "$VIDEODIR" -o -z "$FILENAME" -o -z "$CHAN" -o -z "$START"]; then | |
echo "Usage: $0 <VideoDirectory> <FileName>" | |
exit 5 | |
fi | |
if [ ! -f "$VIDEODIR/$FILENAME" ]; then | |
echo "File does not exist: $VIDEODIR/$FILENAME" | |
exit 6 | |
fi | |
# The meat of the script. Flag commercials, copy the flagged commercials to | |
# the cutlist, and transcode the video to remove the commercials from the | |
# file. | |
echo "Flagging Commercials..." | |
##### - UNCOMMENT FOLLOWING LINE IF RUNNING MythTV Version <= 0.24 | |
#mythcommflag -f $VIDEODIR/$FILENAME | |
##### - UNCOMMENT FOLLOWING LINE IF RUNNING MythTV Version >= 0.25 | |
mythcommflag --chanid $CHAN --starttime $START | |
ERROR=$? | |
if [ $ERROR -gt 126 ]; then | |
echo "Commercial flagging failed for ${FILENAME} with error $ERROR" | |
exit $ERROR | |
fi | |
echo "Generating cutlist..." | |
##### - UNCOMMENT FOLLOWING LINE IF RUNNING MythTV Version <= 0.24 | |
#mythcommflag --gencutlist -f $VIDEODIR/$FILENAME | |
##### - UNCOMMENT FOLLOWING LINE IF RUNNING MythTV Version >= 0.25 | |
mythutil --gencutlist --chanid $CHAN --starttime $START | |
ERROR=$? | |
if [ $ERROR -ne 0 ]; then | |
echo "Copying cutlist failed for ${FILENAME} with error $ERROR" | |
exit $ERROR | |
fi | |
echo "Transcoding..." | |
mythtranscode --honorcutlist --showprogress -i $VIDEODIR/$FILENAME -o $VIDEODIR/$FILENAME.tmp | |
ERROR=$? | |
if [ $ERROR -ne 0 ]; then | |
echo "Transcoding failed for ${FILENAME} with error $ERROR" | |
exit $ERROR | |
fi | |
mv $VIDEODIR/$FILENAME $VIDEODIR/$FILENAME.old | |
mv $VIDEODIR/$FILENAME.tmp $VIDEODIR/$FILENAME | |
echo "Rebuilding..." | |
##### - UNCOMMENT FOLLOWING LINE IF RUNNING MythTV Version <= 0.24 | |
#mythcommflag -f $VIDEODIR/${FILENAME} --rebuild | |
##### - UNCOMMENT FOLLOWING LINE IF RUNNING MythTV Version >= 0.25 | |
mythcommflag --chanid $CHAN --starttime $START --rebuild | |
ERROR=$? | |
if [ $ERROR -ne 0 ]; then | |
echo "Rebuilding seek list failed for ${FILENAME} with error $ERROR" | |
exit $ERROR | |
fi | |
echo "Clearing cutlist..." | |
##### - UNCOMMENT FOLLOWING LINE IF RUNNING MythTV Version <= 0.24 | |
#mythcommflag --clearcutlist -f $VIDEODIR/$FILENAME | |
##### - UNCOMMENT FOLLOWING LINE IF RUNNING MythTV Version >= 0.25 | |
mythutil --clearcutlist --chanid $CHAN --starttime $START | |
ERROR=$? | |
if [ $ERROR -eq 0 ]; then | |
# Fix the database entry for the file | |
##### - Note: MAY need to add mysql mythconverg DB credentials '--user=<blah> --password=<blah>' | |
## to the 'mysql mythconverg' command below.) | |
# Fix the database entry for the file | |
cat << EOF | mysql mythconverg | |
UPDATE | |
recorded | |
SET | |
cutlist = 0, | |
filesize = $(ls -l $VIDEODIR/$FILENAME | awk '{print $5}') | |
WHERE | |
basename = '$FILENAME'; | |
DELETE FROM | |
`recordedmarkup` | |
WHERE | |
CONCAT( chanid, starttime ) IN ( | |
SELECT | |
CONCAT( chanid, starttime ) | |
FROM | |
recorded | |
WHERE | |
basename = '$FILENAME' | |
); | |
EOF | |
exit 0 | |
else | |
echo "Clearing cutlist failed for ${FILENAME} with error $ERROR" | |
rm -f $VIDEODIR/$FILENAME.tmp | |
exit $ERROR | |
fi | |
(END) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment