[mythtv-users] Transcode HD for SD frontend?

Chris Pinkham cpinkham at bc2va.org
Tue Oct 4 07:41:18 UTC 2005


> Is there some way I can tell the backend to transcode (but keep the
> original), and "decide" which version to send when a program is
> selected on the frontend?

This has been brought up before and currently Myth isn't designed to
support anything like this since the database can only handle one
file (and associated filename, seektable, etc.) per recording.

I put together a quick script which might give you what you're
looking for though.

Attached is a script called myth_make_transcoded_copy.pl.  This script
will transcode a recording then take the new .tmp file created by
mythtranscode and rename it and create a new entry in the recording
table with a starttime of 1 minute after the original recording and
a subtitle with " (TRANSCODED)" appended to the original subtitle.  The
AutoExpire field is turned ON for the transcoded copy.  All other fields
remain the same.  The new recording is treated as a separate recording,
there is no link to the original recording, so you have to delete
both of them independently.  I turned AutoExpire ON by default on
the transcoded copy to try to insure the hard drive doesn't fill up
with the transcoded copies.

You would run this script as a User Job from the JobQueue like this (all
on one line):

myth_make_transcoded_copy.pl -c %CHANID% -s %STARTTIME% --dir %DIR%
    --file %FILE%
	
A couple optional args are things like:

    --recgroup 'Transcoded'    (create the new recording in a
                                recording group called "Transcoded"
                                otherwise leave it in the same group)
    --noautoexpire             (turn OFF autoexpire on the new
                                copy of the recording since it defaults
                                to ON).
    --beforeorig               (set starttime of new recording to 1
                                minute BEFORE the original, in case
                                you have autoexpire turned on on both
                                the original and copy, the copy will
                                then expire first since will be older)
	--rebuild                  (build the seektable in the database
                                for the new recording.  This shouldn't
                                be necessary for MPEG4 recordings since
                                they have a seektable in the file)

Additional help is available by typing "myth_make_transcoded_copy.pl -h".

This has only been tested with MPEG2 -> MPEG4 transcodings.  I think
you'll need the --rebuild option with MPEG2 -> MPEG2 transcodings.

> I know I'm asking for a lot here, but I'm guessing someone else must
> have this issue.

Let me know if this works for you, it's something others would probably
be interested in as well.

-- 
Chris Pinkham

-------------- next part --------------
#!/usr/bin/perl
##
## Written by Chris Pinkham (cpinkham at bc2va.org)
##
## Here's the description email I wrote when I originally posted
## this script in reply to a question on the #mythtv-users mailing list.
##
#########################################################################
## > Is there some way I can tell the backend to transcode (but keep the
## > original), and "decide" which version to send when a program is
## > selected on the frontend?
## 
## This has been brought up before and currently Myth isn't designed to
## support anything like this since the database can only handle one
## file (and associated filename, seektable, etc.) per recording.
## 
## I put together a quick script which might give you what you're
## looking for though.
## 
## Attached is a script called myth_make_transcoded_copy.pl.  This script
## will transcode a recording then take the new .tmp file created by
## mythtranscode and rename it and create a new entry in the recording
## table with a starttime of 1 minute after the original recording and
## a subtitle with " (TRANSCODED)" appended to the original subtitle.  The
## AutoExpire field is turned ON for the transcoded copy.  All other fields
## remain the same.  The new recording is treated as a separate recording,
## there is no link to the original recording, so you have to delete
## both of them independently.  I turned AutoExpire ON by default on
## the transcoded copy to try to insure the hard drive doesn't fill up
## with the transcoded copies.
## 
## You would run this script as a User Job from the JobQueue like this (all
## on one line):
## 
## myth_make_transcoded_copy.pl -c %CHANID% -s %STARTTIME% --dir %DIR% 
##     --file %FILE% 
##     
## A couple optional args are things like: 
## 
##     --recgroup 'Transcoded'    (create the new recording in a
##                                 recording group called "Transcoded"
##                                 otherwise leave it in the same group)
##     --noautoexpire             (turn OFF autoexpire on the new
##                                 copy of the recording since it defaults
##                                 to ON).
##     --beforeorig               (set starttime of new recording to 1
##                                 minute BEFORE the original, in case
##                                 you have autoexpire turned on on both
##                                 the original and copy, the copy will
##                                 then expire first since will be older)
##     --rebuild                  (build the seektable in the database
##                                 for the new recording.  This shouldn't
##                                 be necessary for MPEG4 recordings since
##                                 they have a seektable in the file)
## 
## Additional help is available by typing "myth_make_transcoded_copy.pl -h".
## 
## This has only been tested with MPEG2 -> MPEG4 transcodings.  I think
## you'll need the --rebuild option with MPEG2 -> MPEG2 transcodings.
## 
## > I know I'm asking for a lot here, but I'm guessing someone else must
## > have this issue.
## 
## Let me know if this works for you, it's something others would probably
## be interested in as well.
## 
## --
## Chris Pinkham
## 
#########################################################################

require "ctime.pl";
require "timelocal.pl";

use DBI;
use Getopt::Long;

my $chanid = "";
my $orig_startts = "";
my $dir = "";
my $file = "";
my $help = 0;
my $rebuild = 0;
my $database = "mythconverg";
my $dbhost = "localhost";
my $dbuser = "mythtv";
my $dbpass = "mythtv";
my $autoexpire = 1;
my $recgroup = "";
my $beforeorig = 0;

GetOptions(
    'database=s' => \$database,
    'dbhost=s' => \$dbhost,
    'dbuser=s' => \$dbuser,
    'dbpass=s' => \$dbpass,
    'chanid=s' => \$chanid,
    'starttime=s' => \$orig_startts,
    'dir=s' => \$dir,
    'file=s' => \$file,
    'rebuild' => \$rebuild,
    'autoexpire!' => \$autoexpire,
    'beforeorig' => \$beforeorig,
    'recgroup=s' => \$recgroup,
    'help' => \$help
    );

if (( $chanid eq "" ) ||
    ( $orig_startts eq "" ) ||
    ( $dir eq "" ) ||
    ( $file eq "" ) ||
    ( $help != 0 )) {
	print( "Usage: myth_make_transcoded_copy.pl --chanid <CHANID> --startime <STARTTIME> --dir <DIR> --file <FILE> <OPTIONS>\n" );
	print( "\n" );
	print( "WHERE: CHANID    = chanid of program to copy\n" );
	print( "       STARTTIME = starttime in YYYYMMDDHHMMSS format\n" );
    print( "       DIR       = recording directory\n" );
    print( "       FILE      = recording base filename\n" );
    print( "\n" );
    print( "Optional Args:\n" );
    print( "  --rebuild        = build seektable in database for new recording\n" );
    print( "  --noautoexpire   = do not set new recording to autoexpire\n" );
    print( "  --recgroup GROUP = set recording group to GROUP for new recording\n" );
    print( "  --beforeorig     = set time of new recording before original\n" );
	exit(-1);
}

my $sql, $sth;
my $dbh = DBI->connect("dbi:mysql:database=$database:host=$dbhost",
    "$dbuser","$dbpass") or die "Cannot connect to database ($!)\n";

my $s_sec  = substr( $orig_startts, 12, 2);
my $s_min  = substr( $orig_startts, 10, 2);
my $s_hour = substr( $orig_startts, 8, 2);
my $s_mday = substr( $orig_startts, 6, 2);
my $s_mon  = substr( $orig_startts, 4, 2) - 1;
my $s_year = substr( $orig_startts, 0, 4) - 1900;
my $iso_startts = sprintf( "%04d-%02d-%02dT%02d:%02d:%02d",
    $s_year + 1900, $s_mon + 1, $s_mday, $s_hour, $s_min, $s_sec );
my $orig_starttime =
    timelocal( $s_sec, $s_min, $s_hour, $s_mday, $s_mon, $s_year );
my $diff = $beforeorig ? -60 : 60;
my $new_starttime = $orig_starttime + $diff;
my ( $sec,  $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
	localtime($new_starttime);
my $new_startts = sprintf( "%04d%02d%02d%02d%02d%02d",
    $year + 1900, $mon + 1, $mday, $hour, $min, $sec );
my $new_file = $file;
$new_file =~ s/$orig_startts/$new_startts/;

printf( "Transcoding program recorded on chanid %s @ %s\n",
	$chanid, $orig_startts );
printf( "New Recording will be chanid %s @ %s\n",
    $chanid, $new_startts );

if ( -r "$dir/$new_file" ) {
    print( "ERROR: $dir/$new_file already exists, cannot proceed\n" );
    exit(-1);
}

my $cmd = sprintf(
    "mythtranscode --chanid %s --starttime %s -p autodetect",
    $chanid, $iso_startts );

# for testing
#$cmd = sprintf( "ln -s %s/%s %s/%s.tmp", $dir, $file, $dir, $file );

printf( "Running transcode command: '%s'\n", $cmd );

system( $cmd );

if ( ! -r "$dir/$file.tmp" ) {
    print( "ERROR: $dir/$file.tmp does not exist, transcode failed.\n" );
    exit( -1 );
}

print( "Renaming $dir/$file.tmp -> $dir/$new_file\n" );
rename( "$dir/$file.tmp", "$dir/$new_file" );

$sql = sprintf(
    "CREATE TEMPORARY TABLE temp_recorded AS " .
    "SELECT * FROM recorded WHERE chanid = %s AND starttime = %s;",
    $chanid, $orig_startts );
$sth = $dbh->prepare($sql);
$sth->execute() || die "Can't create temporary table temp_recorded!";

$sql = sprintf(
    "UPDATE temp_recorded SET starttime = %s, " .
        "subtitle = CONCAT( subtitle, ' (TRANSCODED)'), " .
        "autoexpire = %d, " .
        "basename = '%s' " .
    "WHERE chanid = %s AND starttime = %s;",
    $new_startts, $autoexpire, $new_file, $chanid, $orig_startts );
$sth = $dbh->prepare($sql);
$sth->execute() || die "Can't modify recording in temp_recorded!";

if ( $recgroup ne "" ) {
    $sql = sprintf(
        "UPDATE temp_recorded SET recgroup = '%s' " .
        "WHERE chanid = %s AND starttime = %s;",
        $recgroup, $chanid, $new_startts );
    $sth = $dbh->prepare($sql);
    $sth->execute() || die "Can't modify recording group in temp_recorded!";
}

$sql = sprintf(
    "INSERT recorded " .
    "SELECT * FROM temp_recorded WHERE chanid = %s AND starttime = %s;",
    $chanid, $new_startts );
$sth = $dbh->prepare($sql);
$sth->execute() || die "Can't insert new recording into recorded table!";

$sql = "DROP TABLE temp_recorded;";
$sth = $dbh->prepare($sql);
$sth->execute();

if ($rebuild) {
    $cmd = sprintf(
        "mythcommflag --chanid %s --starttime %s --rebuild",
        $chanid, $new_startts );
    printf( "Creating seektable in database for new recording\n" );
    printf( "Using '%s'\n", $cmd );
    system( $cmd );
}

# vim: set expandtab tabstop=4 shiftwidth=4:


More information about the mythtv-users mailing list