View unanswered posts    View active topics

All times are UTC - 6 hours





Post new topic Reply to topic  [ 7 posts ] 
Print view Previous topic   Next topic  
Author Message
Search for:
PostPosted: Fri Oct 12, 2007 3:48 am 
Offline
Joined: Tue Oct 17, 2006 10:03 pm
Posts: 49
Hello all,
Here is a modified version of myth2ipod I wrote to rip DVDs to H.264/AAC videos and create an RSS feed for iTunes. I use my KnoppMyth box as a video jukebox rather than a PVR, and I have a dedicated 500GB drive with ripped DVD ISOs on it. This script takes an ISO, mounts it, and rips the video to H.264/AAC. I also put in options to transcode other videos (.avi, etc.) but I haven't tried that yet.

You could easily modify it to directly rip DVDs, but they'd have to be unencrypted, so it's better to just rip to ISO first. The ISO must be indexed by Video Manager to grab the title, plot synopsis, etc. for the RSS feed, and the script is interactive so it must be run from a terminal.

It uses your choice of either ffmpeg or HandBrake (not included in KM by default, but easily added, just go to handbrake.m0k.org and download the Linux command line binary). I added a line to the XML for cover art, do "ln -s /myth/video/.covers /myth/ipodfeed/covers" for it to work, but it doesn't seem to show up properly in iTunes anyway.

Here is the code, comments, suggestions, improvements, etc are welcome:

Code:
#!/usr/bin/perl

use DBI;

my $handbrake_options_ipod_low = "-e x264b30 -b 700 -B 160 -R 48 -E faac -f mp4 -w 320 -x keyint=300:keyint-min=30:bframes=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:subme=6:no-fast-pskip=1 -m";
my $handbrake_options_ipod_hi = "-e x264b30 -b 1500 -B 160 -R 48 -E faac -f mp4 -w 640 -x keyint=300:keyint-min=30:bframes=0:cabac=0:ref=1:vbv-maxrate=1500:vbv-bufsize=2000:analyse=all:me=umh:subme=6:no-fast-pskip=1 -m";
my $handbrake_options_standard = "-e x264 -b 1500 -B 160 -R 48 -E faac -f mp4 -x ref=2:bframes=2:subme=5:me=umh -m -p -2 -T -w 320";
my $handbrake_options_classic = "-b 1000 -B 160 -R 48 -E faac -f mp4 -w 320";

my $ffmpeg_options = "-f mp4 -r 29.97 -vcodec mpeg4 -maxrate 768 -b 700 -qmin 3 -qmax 5 -bufsize 4096 -g 250 -acodec aac -ar 44100 -ab 160 -async 1 -s 320x240 -aspect 4:3";

my $ffmpeg_options_pal = "-f mp4 -r 25 -vcodec mpeg4 -maxrate 768 -b 700 -qmin 3 -qmax 5 -bufsize 4096 -g 250 -acodec aac -ar 44100 -ab 160 -async 1 -s 320x240 -aspect 4:3";

$handbrake = $handbrake_options_ipod_low;

my $portable = "ipod";
# paths for RSS feed, leave these unless you've modified your KM install
my $feedfile = "/myth/ipodfeed/feed.php";
my $feedpath = "/myth/ipodfeed/";
# default path where ISO/video is, you can also specify on the cmd line
my $dvdisopath = "/myth/video/dvd/";
# path where ISO will be mounted
my $mountpath = "/mnt/loop";
# path to www files, leave this unless you've modified your KM install
my $wwwloc = "/var/www/";
my $host = "PUT YOUR HOSTNAME HERE";
my $feedurl = "http://$host/ipodfeed/";

sub DisplayUsage {
        print "usage: dvd2ipod <iso file> <encoder> <directory>\n\nDirectory is optional, if not specified dvd2ipod will look for the file in $dvdisopath\n\nEncoder can be one of:\n\thandbrake: Use HandBrake to convert to H.264/AAC\n\tffmpeg: Use ffmpeg to convert to H.264/AAC\n\tffmpegpal: Use ffmpeg for PAL source\n\n";
        exit;
}

if($ARGV[1] ne "handbrake" && $ARGV[1] ne "ffmpeg" && $ARGV[1] ne "ffmpegpal") {
        print "Invalid encoder\n\n";
        DisplayUsage();
        exit;
} else {
        if($ARGV[1] eq "ffmpegpal") {
                $ffmpeg_options = $ffmpeg_options_pal;
                our $encoder = "ffmpeg";
        } else {
                our $encoder = $ARGV[1];
        }
}


if($ARGV[2]) {
        $dvdisopath = $ARGV[2];
}

my $debug = 1;

if(!($ARGV[0]) || !($ARGV[1])) {!
        DisplayUsage();
}

our $file = $ARGV[0];
our ($basefile, $fileext) = split(/\./,$file);
if($fileext == "iso") {
        $is_iso = 1;
}
our $mountfile = $dvdisopath.$file;
if (! -e $mountfile) {
        print "$file does not exist in $dvdisopath\n";
        exit;
}

print "Encoding file...\n";
Encode4Portable();
if(! -e $feedfile) {
        print "(Re)generating RSS feed...\n";
        GenerateRSSFeed();
}

sub Encode4Portable {
        if($is_iso == 1) {
                system("mount -o loop $mountfile $mountpath");
        }

        PrepSQLRead();
        $db_handle = DBI->connect("dbi:mysql:database=$db_name:host=$db_host", $db_user, $db_pass) or die "Cannot connect to database\n";

        $sql = "SELECT title,plot,category,coverfile,rating,year,length FROM videometadata WHERE filename='$mountfile'";

        if($debug == 1) { print "SQL: $sql\n"; }

        $statement = $db_handle->prepare($sql) or die "Couldn't prepare query $sql: $DBI::errstr\n";
        $statement->execute() or die "Couldn't execute query $sql: $DBI::errstr\n";
        $row_ref = $statement->fetchrow_hashref();

        $title = $row_ref->{title};
        $description = $row_ref->{plot};
        $category = $row_ref->{category};
        $coverfile = $row_ref->{coverfile};
        $rating = $row_ref->{rating};
        $year = $row_ref->{year};
        $length = $row_ref->{length};
        $filename = $mountfile;

        printf("Starting encoder...\n");
                EncodeIt();
        printf("Encoding complete. Generating RSS...\n");
                CreateItemXML();
        printf("XML created for $filename\n");
        printf("Cleaning up...\n");
                if($is_iso == 1) {
                        system("umount $mountpath");
                }
                system("rm -f $feedpath$basefile.temp.mp4");
}

sub EncodeIt {
        if($is_iso == 1) {
                if($encoder eq "handbrake") {
                        system("/usr/local/bin/HandBrakeCLI -i $mountpath/VIDEO_TS -t 0");
                        $titletorip = &promptUser("\nSelect a title to rip: ","1");
                        $outfile = $basefile."_title$titletorip".".temp.mp4";
                        $outpath = $feedpath.$outfile;
                        $finaloutpath = $feedpath.$basefile."_title$titletorip".".".$portable.".mp4";
                        $cmd = "/usr/local/bin/HandBrakeCLI -i $mountpath/VIDEO_TS -o $outpath -t $titletorip $handbrake";
                }

                if($encoder eq "ffmpeg") {
                        $outfile = $basefile.".temp.mp4";
                        $outpath = $feedpath.$outfile;
                        $finaloutpath = $feedpath.$basefile.".".$portable.".mp4";
                        $cmd = "cat $mountpath/VIDEO_TS/*.VOB | ffmpeg -i - $ffmpeg_options $outpath";
                }
        } else {
                $outfile = $basefile.".temp.mp4";
                $outpath = $feedpath.$outfile;
                $finaloutpath = $feedpath.$basefile.".".$portable.".mp4";
                if($encoder eq "handbrake") {
                        $cmd = "/usr/local/bin/HandBrakeCLI -i $dvdisopath/$file -o $outpath $handbrake";
                }

                if($encoder eq "ffmpeg") {
                        $cmd = "ffmpeg -i $dvdisopath/$file $ffmpeg_options $outpath";
                }
        }

        if($debug == 1) { print "Encoder: $cmd\n"; }
        if(system($cmd)) { print "Encoder failed.\n"; }

        $cmd = "/usr/local/bin/MP4Box -add $outpath $finaloutpath";
        if($debug == 1) { print "MP4Box: $cmd\n"; }
        if(system($cmd)) { print "MP4Box cleanup failed.\n"; }
}

sub CreateItemXML {
        $usetitle = &promptUser("\nEnter a title (hit return for \"$title\"): ",$title);
        $usedescription = &promptUser("\nEnter a description (hit return for \"$description\"): ",$description);
        $finalouturl = $feedurl.$basefile.".".$portable.".mp4";
        my ($a, $b, $c, $d, $cover) = split("/", $coverfile);
        my $coverurl = $feedurl."covers/".$cover;
        open(ITEM, ">$feedpath$basefile.$portable.xml");
                print ITEM "<item>\n";
                print ITEM "<title>".&encodeForXML($usetitle)."</title>\n";
                print ITEM "<itunes:author>MythTV</itunes:author>\n";
                print ITEM "<author>MythTV</author>\n";
                print ITEM "<itunes:category text=\"Movies\"></itunes:category>\n";
                print ITEM "<comments>".&encodeForXML($file)."</comments>\n";
                print ITEM "<description>".&encodeForXML($usedescription)."</description>\n";
                print ITEM "<pubDate>".&encodeForXML(`date`)."</pubDate>\n";
                print ITEM "<enclosure url=\"".&encodeForXML($finalouturl)."\" type=\"video/quicktime\" />\n";
                print ITEM "<itunes:duration></itunes:duration>\n";
                print ITEM "<itunes:keywords>".&encodeForXML($title)."</itunes:keywords>\n";
                print ITEM "<itunes:image href=\"".&encodeForXML($coverurl)."\" />\n";
                print ITEM "</item>\n";
                print "$filename added to feed.\n";
        close(ITEM);
        return 0;
}

sub GenerateRSSFeed {
        open(RSS, ">$feedfile");
                print RSS "<?php\n";
                print RSS "header(\"Content-Type: text/xml\");\n";
                print RSS "echo \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\"; ?>\n";
                print RSS "<rss xmlns:itunes=\"http://www.itunes.com/DTDs/Podcast-1.0.dtd\" version=\"2.0\">\n";
                print RSS "<channel>\n";
                print RSS "<title>MythTV - <? if (\$_GET['title'] == \"\") { \$title = \"*\"; echo \"Recorded Programs\"; }\n";
                print RSS "else { \$title = \$_GET['title']; echo str_replace(\"_\",\" \",\$_GET['title']); } ?> </title>\n";
                print RSS "<itunes:author>MythTV - myth2ipod</itunes:author>\n";
                print RSS "<link>".&encodeForXML($feedurl)."</link>\n";
                print RSS "<itunes:subtitle>Transcoded recording for your iPod Video.</itunes:subtitle>\n";
                print RSS "<itunes:summary>Myth TV Recorded Programs for the iPod v.1</itunes:summary>\n";
                print RSS "<description>Myth TV Recorded Programs for the iPod v.1</description>\n";
                print RSS "<itunes:owner>\n";
                print RSS "<itunes:name>MythTV</itunes:name>\n";
                print RSS "<itunes:email>mythtv\@localhost</itunes:email>\n";
                print RSS "</itunes:owner>\n";
                print RSS "<itunes:explicit>No</itunes:explicit>\n";
                print RSS "<language>en-us</language>\n";
                print RSS "<copyright>Copyright 2005.</copyright>\n";
                print RSS "<webMaster>mythtv\@localhost</webMaster>\n";
                print RSS "<itunes:image href=\"http://myth2ipod.com/mythipod_200.jpg\" />\n";
                print RSS "<itunes:category text=\"TV Shows\"></itunes:category>\n";
                print RSS "<category>TV Shows</category>\n";
                print RSS "<itunes:image href=\"http://myth2ipod.com/mythipod_200.jpg\"/>";
                print RSS "<image>";
                print RSS "<url>http://myth2ipod.com/mythipod_200.jpg</url>\n";
                print RSS "<title>MythTV 2 iPod</title>\n";
                print RSS "<link>".&encodeForXML($feedurl)."</link>\n";
                print RSS "<width>200</width>\n";
                print RSS "<height>200</height>\n";
                print RSS "</image>\n";
                print RSS "<? foreach (glob(\$title\.\"*\.$portable\.xml\") as \$file) {include \$file;} ?>\n";
                print RSS "</channel>\n";
                print RSS "</rss>\n";
        close(RSS);
        if($debug == 1){ print "I created a feed file, was I supposed to?\n"};

        return 0;
}

#
# This code taken from one of the mythlink.sh scripts to get MySQL information
#
sub PrepSQLRead{
# Get the hostname of this machine
    $hostname = `hostname`;
    chomp($hostname);
   
# Read the mysql.txt file in use by MythTV.
# could be in a couple places, so try the usual suspects
    my $found = 0;
    my @mysql = ('/usr/local/share/mythtv/mysql.txt',
                 '/usr/share/mythtv/mysql.txt',
                 '/etc/mythtv/mysql.txt',
                 '/usr/local/etc/mythtv/mysql.txt',
                 "$ENV{HOME}/.mythtv/mysql.txt",
                 'mysql.txt'
                );
    foreach my $file (@mysql) {
        next unless (-e $file);
        $found = 1;
        open(CONF, $file) or die "Unable to open $file:  $!\n\n";
        while (my $line = <CONF>) {
        # Cleanup
            next if ($line =~ /^\s*#/);
            $line =~ s/^str //;
            chomp($line);
        # Split off the var=val pairs
            my ($var, $val) = split(/\=/, $line, 2);
            next unless ($var && $var =~ /\w/);
            if ($var eq 'DBHostName') {
                $db_host = $val;
            }
            elsif ($var eq 'DBUserName') {
                $db_user = $val;
            }
            elsif ($var eq 'DBName') {
                $db_name = $val;
            }
            elsif ($var eq 'DBPassword') {
                $db_pass = $val;
            }
        # Hostname override
            elsif ($var eq 'LocalHostName') {
                $hostname = $val;
            }
        }
        close CONF;
    }
    die "Unable to locate mysql.txt:  $!\n\n" unless ($found && $db_host);
    return 0;
}

sub promptUser {
   local($promptString,$defaultValue) = @_;
   if ($defaultValue) {
      print $promptString, "[", $defaultValue, "]: ";
   } else {
      print $promptString, ": ";
   }

   $| = 1;               # force a flush after our print
   $_ = <STDIN>;         # get the input from STDIN (presumably the keyboard)
   chomp;
   if ("$defaultValue") {
      return $_ ? $_ : $defaultValue;    # return $_ if it has a value
   } else {
      return $_;
   }
}

# substitute for XML entities
sub encodeForXML {
        local $result;
        $result = $_[0];
        $result =~ s/&/&amp;/g;
        $result =~ s/</&lt;/g;
        $result =~ s/>/&gt;/g;
        $result;
}


Last edited by nickca on Fri Oct 12, 2007 6:20 pm, edited 4 times in total.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 12, 2007 3:50 am 
Offline
Joined: Tue Oct 17, 2006 10:03 pm
Posts: 49
Oh, and just for grins, here's the script I use to rip DVDs. I got this from somewhere else and modified it some.

Code:
#!/bin/sh
#script to backup full dvd's including menu's
#needs the dvdbackup tool from http://dvd.chevelless230.com/dvdbackup.html
# set these to match your system settings
dvddevice="/dev/dvd"
# temp storage while creating iso image (could use tmp if that is on a big partition)
dvdstorage="/media/sdb1/temp"
mythvideodir="/media/sdb1/iso"

##################################
#make a complete copy of the dvd
echo "Copying DVD"
dvdbackup -i $dvddevice -o $dvdstorage -M

naam=`ls $dvdstorage`
#get the DVD name from the foldername created by dvdbackup
echo  $dvdstorage"/"$naam
echo  $mythvideodir"/"$naam

echo "Creating ISO"
mkisofs -dvd-video -udf -V "Backup DVD" $dvdstorage"/"$naam > $mythvideodir"/"$naam".iso"
chown mythtv.mythtv $mythvideodir"/"$naam".iso"

echo "Cleaning up"
rm -rf /media/sdb1/temp/*

#echo "Squashing ISO"
#mksquashfs $mythvideodir"/"$naam".iso" $mythvideodir"/"$naam".squash" -no-duplicates
#rm $mythvideodir"/"$naam".iso"

mythtvosd --template=alert --alert_text='DVD rip completed!'
aplay /home/nickca/rip_completed.wav


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 12, 2007 6:21 am 
Offline
Joined: Fri Nov 18, 2005 9:22 am
Posts: 777
Location: spencerport, ny (USA)
This sounds great. I need this. Thanks for contributing.
I hope to check it out this weekend.
--
Chris


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 16, 2007 6:27 pm 
Offline
Joined: Fri Nov 18, 2005 9:22 am
Posts: 777
Location: spencerport, ny (USA)
Something wrong?
I get this:

Code:
root@mythtv:/# dvd2ipod.sh SOME_DVD.iso handbrake
Encoding file...
mount: mount point /mnt/loop does not exist
SQL: SELECT title,plot,category,coverfile,rating,year,length FROM videometadata WHERE filename='/myth/video/dvd/SOME_DVD.iso'
Starting encoder...
HandBrake 0.9.1 (2007100800) - http://handbrake.m0k.org/
1 CPU detected
Opening /mnt/loop/VIDEO_TS...
ERROR: dvd: DVDOpen failed (/mnt/loop/VIDEO_TS)No title found.
HandBrake has exited.


I tried ffmpeg too...
Maybe there's a step that you did, that I didn't do?
I'm on R5F27.
Probem seems to be /mnt/loop


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 16, 2007 6:40 pm 
Offline
Joined: Fri Nov 18, 2005 9:22 am
Posts: 777
Location: spencerport, ny (USA)
Duh, I tried creating /mnt/loop and now it's running.... I'll report back.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 21, 2007 2:27 pm 
Offline
Joined: Tue Oct 17, 2006 10:03 pm
Posts: 49
It doesn't necessarily have to be /mnt/loop, all the variables at the top (inluding the HandBrake and ffmpeg options) can be changed to whatever you want. Also, unless you're running a DNS server on your local network or have added the IP address and hostname to the hosts file of whatever machine(s) you run iTunes on, it's easier to just put the IP address of your Myth box where it says "PUT YOUR HOSTNAME HERE" instead of the hostname. Same goes for the stock myth2ipod. For example, mine is set to 192.168.0.153 instead of the hostname "vidiot". Oh, and you will have problems with both this and myth2ipod (and mythweb and any number of other things) if your myth box is getting its IP address from DHCP rather than a static IP that you've set. Do "man interfaces", read it, and edit /etc/network/interfaces to set up a static IP.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 23, 2007 12:13 pm 
Offline
Joined: Fri Oct 20, 2006 12:04 pm
Posts: 905
Location: LA, CA
This looks real handy. Will it work for .vob rips as well as iso's ?


Top
 Profile  
 

Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 


All times are UTC - 6 hours




Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
Powered by phpBB® Forum Software © phpBB Group

Theme Created By ceyhansuyu