<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>EdSalisbury.net : Your Guide to User-Friendly Entertainment &#187; Videos</title>
	<atom:link href="http://www.edsalisbury.net/category/videos/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.edsalisbury.net</link>
	<description>Your Guide to User-Friendly Entertainment</description>
	<lastBuildDate>Mon, 14 Jun 2010 00:38:57 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>How to Convert DVDs and TiVo MPEG2 Videos to H.264</title>
		<link>http://www.edsalisbury.net/linux/how-to-convert-dvds-and-tivo-mpeg2-videos-to-h-264/</link>
		<comments>http://www.edsalisbury.net/linux/how-to-convert-dvds-and-tivo-mpeg2-videos-to-h-264/#comments</comments>
		<pubDate>Wed, 22 Jul 2009 02:31:52 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[TiVo]]></category>
		<category><![CDATA[Videos]]></category>
		<category><![CDATA[dvd]]></category>
		<category><![CDATA[h.264]]></category>
		<category><![CDATA[mpeg2]]></category>

		<guid isPermaLink="false">http://www.edsalisbury.net/?p=353</guid>
		<description><![CDATA[
Previously, I have showed you how to set up software to be able to rip DVDs to your hard drive, and I&#8217;ve also shown you how to copy your TiVo videos nightly.  I&#8217;ve described the method I use to transcode the videos, but haven&#8217;t provided the script&#8230; Until now.  After months of using [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.edsalisbury.net/wp-content/uploads/2009/07/Sony-H_264-compress-250-150x150.jpg" alt="H.264" title="H.264" width="150" height="150" class="alignright size-thumbnail wp-image-357" /><br />
Previously, I have showed you how to set up software to be able to <a href="http://www.edsalisbury.net/linux/how-to-rip-dvds-on-ubuntu-linux-9-04-jaunty/">rip DVDs</a> to your hard drive, and I&#8217;ve also shown you how to <a href="http://www.edsalisbury.net/linux/how-to-copy-videos-from-a-series-3-tivo-to-ubuntu-linux/">copy your TiVo videos</a> nightly.  I&#8217;ve described the method I use to <a href="http://www.edsalisbury.net/linux/how-to-convert-tivo-mpeg2-videos-to-h264/">transcode</a> the videos, but haven&#8217;t provided the script&#8230; Until now.  After months of using and tweaking, here&#8217;s what I use.  I call it VidProc.</p>
<p><span id="more-353"></span></p>
<pre class="brush:perl; gutter: false; wrap-lines: true; ruler: false">
#!/usr/bin/perl
# VidProc
# Transcode videos that have been either ripped by ripper or copied from a TiVo
#    to H.264 format
# by Ed Salisbury (ed@edsalisbury.net)
# http://www.edsalisbury.net
# (c)2009 Ed Salisbury, Some Rights Reserved
#
# External Utilities Required:
# * HandBrakeCLI
# * MPlayer/Mencoder
#
# Notes:
# * Settings for HandBrake and mencoder are what I have come up with after
#   doing a fair bit of research, and seem to work pretty well - if you have
#   any concrete suggestions on *better* general-purpose settings, let me know.
#
# License:
# Except where otherwise noted, this work is licensed under Creative Commons
#   Attribution ShareAlike 3.0.
#
# You are free:
#   * to Share -- to copy, distribute and transmit the work
#   * to Remix -- to adapt the work
#
# Under the following conditions:
#   * Attribution. You must attribute the work in the manner specified by the
#     author or licensor (but not in any way that suggests that they endorse
#     you or your use of the work).
#   * Share Alike. If you alter, transform, or build upon this work, you may
#     distribute the resulting work only under the same, similar or a
#     compatible license.
#   * For any reuse or distribution, you must make clear to others the license
#     terms of this work. The best way to do this is with a link to the
#     license's web page (http://creativecommons.org/licenses/by-sa/3.0/)
#   * Any of the above conditions can be waived if you get permission from the
#     copyright holder.
#   * Nothing in this license impairs or restricts the author's moral rights.

use warnings;
use strict;
use File::Copy;
use File::Basename;

sub system_int($);

# Locations
my $DEST = &quot;/path/to/destdir&quot;;
my $QUEUE = &quot;/path/to/queue.txt&quot;;

# Encoding Options
my $DEINT = &quot;pp=md&quot;;    # Deinterlacer
my $VBITRATE = 1000;    # Video Bitrate
my $SAMPLE_RATE = 44.1; # Audio Sample Rate
my $ABITRATE = 192;     # Audio Bitrate
my $OVERSCAN = 6;       # Overscan size (# of lines)

# File Extensions
my $SRC_EXT = &quot;mpg&quot;;
my $DEST_EXT = &quot;mp4&quot;;

# External Utilities
my $HANDBRAKE = &quot;/usr/local/bin/HandBrakeCLI&quot;;
my $MENCODER = &quot;/usr/bin/mencoder&quot;;
my $MPLAYER = &quot;/usr/bin/mplayer&quot;;

# Add backslashes to spaces
$DEST =~ s/ /\\ /g;

while (1)
{
    # Read in the queue
    open(QUEUE, $QUEUE);
    my $line = &lt;QUEUE&gt;;
    my @fields;
    if ($line)
    {
        chomp ($line);
        @fields = split(/\|/, $line);
    }
    else
    {
        print &quot;Waiting for new stuff to show up in the queue...\n&quot;;
        close(QUEUE);
        sleep(60);
        next;
    }
    close (QUEUE);

    my $input = $fields[0];

    print &quot;Processing $input\n&quot;;

    # Fix spaces
    $input =~ s/ /\\ /g;
    $input =~ s/'/\\'/g;
    $input =~ s/&amp;/\\&amp;/g;
    $input =~ s/;/\\;/g;
    my @extlist = (&quot;.$SRC_EXT&quot;);

    my $base = basename($input, @extlist);

    if ($fields[1])
    {
        # DVD, since it has a title number
        my $title = $fields[1];
        my $output = &quot;$DEST/${base}_&quot; . $fields[1] . &quot;.$DEST_EXT&quot;;

        system_int(&quot;$HANDBRAKE --input $input --output $output --title $title --turbo --encoder x264 --vb $VBITRATE --audio 1 --aencoder faac --mixdown 6ch --arate $SAMPLE_RATE --ab $ABITRATE --detelecine --decomb --loosePixelratio --markers --two-pass --x264opts ref=3:mixed-refs:bframes=6:weightb:direct=auto:b-pyramid:me=umh:subme=9:analyse=all:8x8dct:trellis=1:nr=150:no-fast-pskip=1:psy-rd=1,1&quot;);
    }
    else
    {
        # TiVo file, since it has no title number
        my $output = &quot;$DEST/${base}.$DEST_EXT&quot;;
        my $line;
        my $width;
        my $height;

        # Get video dimensions
        print &quot;Getting video information... &quot;;
        my @id = `$MPLAYER -nojoystick -nolirc -vo null -ao null -identify -frames 0 $input 2&gt;&amp;1`;
        foreach (@id)
        {
            if (/ID_VIDEO_WIDTH=(\d+)/)
            {
                $width = $1;
            }
            if (/ID_VIDEO_HEIGHT=(\d+)/)
            {
                $height = $1;
            }
        }
        if (!$width || !$height)
        {
            print &quot;FAILED!&quot;;
        }
        else
        {
            print &quot;(${width}x$height)\n&quot;;
        }

        # Crop overscan
        $height-=$OVERSCAN;

        my %croptest;

        # Detect crop region
        print &quot;Detecting crop region... &quot;;
        my @cropdetect = `$MPLAYER -nojoystick -nolirc -vo null -ao null -vf crop=$width:$height:0:$OVERSCAN,cropdetect -ss 600 -endpos 180 $input 2&gt;&amp;1`;
        foreach $line (@cropdetect)
        {
            if ($line =~ /-vf crop=([\d:]+)/)
            {
                $croptest{$1}++;
            }
        }

        # Get the crop value with the most hits
        my @croplist = sort { $croptest{$b} &lt;=&gt; $croptest{$a} } keys (%croptest);
        my $crop = $croplist[0];

        if (!$crop)
        {
            print &quot;FAILED\n&quot;;
            exit();
        }
        print &quot;($crop)\n&quot;;
        print '-' x 80 . &quot;\n&quot;;

        print &quot;Encoding first pass\n&quot;;
        print '-' x 80 . &quot;\n&quot;;
        system_int(&quot;$MENCODER -ovc x264 -x264encopts pass=1:turbo:bitrate=$VBITRATE:bframes=1:me=umh:partitions=all:trellis=1:qp_step=4:qcomp=0.7:direct_pred=auto:keyint=300 -vf $DEINT,crop=$crop,scale=-1:-10,harddup -oac copy -ofps 30000/1001 $input -o /dev/null&quot;);

        print &quot;\n\n&quot;;
        print '-' x 80 . &quot;\n&quot;;
        print &quot;Encoding second pass\n&quot;;
        print '-' x 80 . &quot;\n&quot;;
        system_int(&quot;$MENCODER -ovc x264 -x264encopts pass=2:turbo:bitrate=$VBITRATE:bframes=1:me=umh:partitions=all:trellis=1:qp_step=4:qcomp=0.7:direct_pred=auto:keyint=300 -vf $DEINT,crop=$crop,scale=-1:-10:,harddup -oac copy -ofps 30000/1001 $input -o $output&quot;);
    }
    print &quot;Done. Removing from queue\n&quot;;
    print &quot;\n\n&quot;;
    open(IN, $QUEUE);
    open(OUT, &quot;&gt;$QUEUE.tmp&quot;);
    while (my $qline = &lt;IN&gt;)
    {
        chomp ($qline);
        unless ($line eq $qline)
        {
            print OUT &quot;$qline\n&quot;;
        }
    }
    close (IN);
    close (OUT);
    unlink($QUEUE);
    move(&quot;$QUEUE.tmp&quot;, $QUEUE);
}

# Interruptible System Command
sub system_int($)
{
    my ($cmd) = @_;
    my $pid = fork();
    my $rc;
    if ($pid == 0)
    {
        exec($cmd);
    }
    else
    {
        waitpid($pid,0);
        $rc = $?;
    }
    return $rc;
}
</pre>
<p>It uses the same queue file that the other scripts will write to, so think of this as a continuation of the previous articles.  To use it, stick it somewhere like /usr/local/bin, and then change the locations to be wherever your queue is, and where you want your videos to end up.  The transcoding settings can get a little hairy, so I would say don&#8217;t mess with the actual command lines unless you know what you&#8217;re doing (but, if you did, you probably wouldn&#8217;t need this script!)</p>
<h4>External Utilities Needed:</h4>
<p>HandBrakeCLI &#8211; this can be downloaded from <a href="http://handbrake.fr/?article=download">here</a><br />
mplayer/mencoder &#8211; This can be installed via apt-get</p>
<h4>A couple of Notes/FAQs:</h4>
<p><b>Overscan removal:</b><br />
If you deal with letterboxed videos copied from TV, you&#8217;ll know what a pain overscan can be &#8211; Overscan is the generic term for the fuzzy line above the video that gets really annoying when watching on your monitor, but not on your TV.  This can wreak havoc with detecting where to crop the video, so I remove it.</p>
<p><b>HandBrake *AND* mencoder??  Why?</b><br />
I found that for some reason, Handbrake didn&#8217;t like working with the files that were copied from the TiVo &#8211; I dealt with lots of weird sync issues.  I posted it on the Handbrake forum, but never got a solution.  I ended up just using mencoder for the TiVo files, and Handbrake for the DVD rips, and left it at that.</p>
<p><b>Your setting XXX sucks &#8211; you should use YYY!</b><br />
If you can state that for any type of program (animation, TV, letterboxed, HD, etc.) that this is correct (and that it doesn&#8217;t make the process take much longer), I&#8217;ll happily thank you and update the script (as well as give you a mention here.)  I spent a bit of time trying to find settings that would work well for what I wanted, and ended up choosing these.  They&#8217;re not going to have the <b>best</b> quality, but the size and the time to transcode were good, so that&#8217;s what I stuck with.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.edsalisbury.net/linux/how-to-convert-dvds-and-tivo-mpeg2-videos-to-h-264/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>How to Copy Videos from a Series 3 TiVo to Ubuntu Linux</title>
		<link>http://www.edsalisbury.net/linux/how-to-copy-videos-from-a-series-3-tivo-to-ubuntu-linux/</link>
		<comments>http://www.edsalisbury.net/linux/how-to-copy-videos-from-a-series-3-tivo-to-ubuntu-linux/#comments</comments>
		<pubDate>Sat, 18 Jul 2009 05:27:19 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[TiVo]]></category>
		<category><![CDATA[Videos]]></category>

		<guid isPermaLink="false">http://www.edsalisbury.net/?p=341</guid>
		<description><![CDATA[
This guide will show you how to set up a script to copy programs from your Series 3 TiVo on a regular basis, without having to do a thing after it&#8217;s set up!
Information you will need:

Your TiVo&#8217;s IP Address (needs to be static)
Your TiVo&#8217;s Media Access Key (MAK) &#8211; this can be found on tivo.com [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.edsalisbury.net/wp-content/uploads/2009/07/tivo-logo1-134x150.jpg" alt="TiVo" title="TiVo" width="134" height="150" class="alignleft size-thumbnail wp-image-298" /><br />
This guide will show you how to set up a script to copy programs from your Series 3 TiVo on a regular basis, without having to do a thing after it&#8217;s set up!</p>
<p>Information you will need:</p>
<ul>
<li>Your TiVo&#8217;s IP Address (needs to be static)</li>
<li>Your TiVo&#8217;s Media Access Key (MAK) &#8211; this can be found on tivo.com after you&#8217;ve logged in</li>
<li>The location where you want your files to be dumped (they are *big* &#8211; figure 1 GB per hour for SD, and like 5 GB per hour for HD)</li>
<li>The location where the files will eventually be stored</li>
</ul>
<p><span id="more-341"></span></p>
<p>The external utilities you will need:</p>
<ul>
<li>Curl &#8211; Install via <code>sudo apt-get install curl</code></li>
<li>Tivodecode &#8211; download from <a href="http://sourceforge.net/projects/tivodecode/files/">Sourceforge</a></li>
</ul>
<p>You will also need to install the following <a href="http://www.edsalisbury.net/linux/installing-perl-modules-on-ubuntu/">CPAN</a> perl modules:</p>
<ul>
<li>Net::TiVo</li>
<li>XML::Simple</li>
<li>Text::Unidecode</li>
</ul>
<p>After you have all of that stuff installed and info gathered, it&#8217;s time to install my tivo_dump script:</p>
<pre class="brush:perl; gutter: false; wrap-lines: true; ruler: false">
#!/usr/bin/perl
# TiVo Dump
# Copy TiVo programs from a Series3 TiVo
# by Ed Salisbury (ed@edsalisbury.net)
# http://www.edsalisbury.net
# (c)2009 Ed Salisbury, Some Rights Reserved
#
# External Utilities Required:
# * curl
# * tivodecode
#
# External Perl Modules Required:
# * Net::TiVo
# * XML::Simple
# * Text::Unidecode;
#
# Usage:
# tivo_dump
#
# License:
# Except where otherwise noted, this work is licensed under Creative Commons
#   Attribution ShareAlike 3.0.
#
# You are free:
#   * to Share - to copy, distribute and transmit the work
#   * to Remix - to adapt the work
#
# Under the following conditions:
#   * Attribution. You must attribute the work in the manner specified by the
#     author or licensor (but not in any way that suggests that they endorse
#     you or your use of the work).
#   * Share Alike. If you alter, transform, or build upon this work, you may
#     distribute the resulting work only under the same, similar or a
#     compatible license.
#   * For any reuse or distribution, you must make clear to others the license
#     terms of this work. The best way to do this is with a link to the
#     license's web page (http://creativecommons.org/licenses/by-sa/3.0/)
#   * Any of the above conditions can be waived if you get permission from the
#     copyright holder.
#   * Nothing in this license impairs or restricts the author's moral rights.

use warnings;
use strict;
use Net::TiVo;
use XML::Simple;
use utf8;
use Text::Unidecode;

sub fix_chars($);

# User-Configurable Variables
my $HOST = &quot;&quot;;      # Hostname/IP of the TiVo
my $MAK = &quot;&quot;;       # The Media Access Key of the TiVo
my $VIDEO_DIR = &quot;&quot;; # Where the programs get saved
my $COPY_SUGGESTIONS = 0; # If you want to copy &quot;Suggested&quot; programs, set this to 1

my $USER = &quot;tivo&quot;;
my $TMPFILE = &quot;/tmp/$$.xml&quot;;
my $PROGRAMS_FILE = &quot;/home/username/.tivo_programs&quot;;
$|++;

# External Utilities
my $CURL = &quot;/usr/bin/curl&quot;;
my $TIVODECODE = &quot;/usr/local/bin/tivodecode&quot;;

my @PREV;

# Connect to the TiVo
print &quot;Connecting to TiVo at $HOST... &quot;;
my $tivo = Net::TiVo-&gt;new(host =&gt; $HOST, mac =&gt; $MAK);
my @folders = $tivo-&gt;folders();
if (@folders)
{
    print &quot;OK\n&quot;;
}
else
{
    print &quot;FAIL\n&quot;;
    exit();
}

# Load the file that has the previously saved programs
open(IN, $PROGRAMS_FILE);
while (&lt;IN&gt;)
{
    chop();
    push(@PREV, $_);
}
close (IN);

# Go through each folder on the TiVo
foreach my $folder (@folders)
{
    foreach my $item ($folder-&gt;{'xmlref'}{'Item'})
    {
        foreach my $video (@$item)
        {
            # Only process videos, not folders
            if ($video-&gt;{'Links'}{'Content'}{'ContentType'} eq &quot;video/x-tivo-raw-tts&quot;)
            {
                # Choose video type based on the icon
                if ($video-&gt;{'Links'}{'CustomIcon'} &amp;&amp; $video-&gt;{'Links'}{'CustomIcon'}{'Url'} eq &quot;urn:tivo:image:suggestion-recording&quot; &amp;&amp; !$COPY_SUGGESTIONS)
                {
                    next;
                }
                if ($video-&gt;{'Links'}{'CustomIcon'} &amp;&amp;
                   ($video-&gt;{'Links'}{'CustomIcon'}{'Url'} eq &quot;urn:tivo:image:in-progress-transfer&quot; ||
                    $video-&gt;{'Links'}{'CustomIcon'}{'Url'} eq &quot;urn:tivo:image:in-progress-recording&quot;))
                {
                   next;
                }

                # Get program and episode titles
                my $program_title = $video-&gt;{'Details'}{'Title'};

                if ($video-&gt;{'Details'}{'EpisodeTitle'})
                {
                    $program_title .= &quot; - &quot; . $video-&gt;{'Details'}{'EpisodeTitle'};
                }

                # Get Program ID and Video URL
                my $video_url = $video-&gt;{'Links'}{'Content'}{'Url'};
                my $program_id = $video-&gt;{'Details'}{'ProgramId'};

                if (!$program_id)
                {
                    next;
                }

                # If previously copied, skip
                if (grep /^$program_id$/, @PREV)
                {
                    print &quot;Skipping $program_title.\n&quot;;
                    next;
                }

                # get details XML file
                print &quot;Getting details for $program_title... &quot;;
                my $details_xml = $video-&gt;{'Links'}{'TiVoVideoDetails'}{'Url'};

                system(&quot;$CURL --digest -s -k -u $USER:$MAK -c /tmp/cookies.txt -o $TMPFILE \&quot;$details_xml\&quot;&quot;);
                if (-f $TMPFILE)
                {
                    print &quot;OK\nProcessing details file... &quot;;
                    my $xml = XML::Simple-&gt;new();
                    my $doc = $xml-&gt;XMLin($TMPFILE);
                    my %meta;
                    my $filepath;
                    my $filename;

                    # Get rating and convert to proper form
                    $meta{'tvRating'} = $doc-&gt;{'showing'}{'tvRating'}{'content'};
                    if ($meta{'tvRating'})
                    {
                        if ($meta{'tvRating'} eq &quot;Y_7&quot;) { $meta{'tvRating'} = 'x1'; }
                        elsif ($meta{'tvRating'} eq &quot;PG&quot;) { $meta{'tvRating'} = 'x4'; }
                        elsif ($meta{'tvRating'} eq &quot;_14&quot;) { $meta{'tvRating'} = 'x5'; }
                        else { $meta{'tvRating'} = &quot;x7&quot;; }
                    }

                    # Get other data
                    $meta{'vActor'} = $doc-&gt;{'showing'}{'program'}{'vActor'}{'element'};
                    $meta{'vDirector'} = $doc-&gt;{'showing'}{'program'}{'vDirector'}{'element'};
                    $meta{'vProgramGenre'} = $doc-&gt;{'showing'}{'program'}{'vProgramGenre'}{'element'};
                    $meta{'vSeriesGenre'} = $doc-&gt;{'showing'}{'program'}{'series'}{'vSeriesGenre'}{'element'};
                    $meta{'seriesTitle'} = $doc-&gt;{'showing'}{'program'}{'series'}{'seriesTitle'};
                    $meta{'title'} = $doc-&gt;{'showing'}{'program'}{'title'};
                    $meta{'isEpisode'} = $doc-&gt;{'showing'}{'program'}{'isEpisode'};
                    $meta{'originalAirDate'} = $doc-&gt;{'showing'}{'program'}{'originalAirDate'};
                    $meta{'episodeTitle'} = $doc-&gt;{'showing'}{'program'}{'episodeTitle'};
                    $meta{'description'} = $doc-&gt;{'showing'}{'program'}{'description'};

                    if (defined $meta{'description'})
                    {
                        $meta{'description'} =~ s/\s+Copyright.*$//;
                    }

                    # Process Titles

                    $meta{'episodeNumber'} = $doc-&gt;{'showing'}{'program'}{'episodeNumber'};

                    my $series_title = '';
                    my $episode_number = '';
                    my $episode_title = '';
                    my $title = '';

                    if ($meta{'seriesTitle'})
                    {
                        $series_title = fix_chars($meta{'seriesTitle'});
                    }
                    if ($meta{'episodeNumber'})
                    {
                        $episode_number = fix_chars($meta{'episodeNumber'});
                    }
                    if ($meta{'episodeTitle'})
                    {
                        $episode_title = fix_chars($meta{'episodeTitle'});
                    }
                    if ($meta{'title'})
                    {
                        $title = fix_chars($meta{'title'});
                    }

                    if ($series_title &amp;&amp; $episode_number &amp;&amp; $episode_title)
                    {
                        $filepath = &quot;$VIDEO_DIR/$series_title&quot;;
                        $filename = &quot;$filepath/$series_title - $episode_number - $episode_title&quot;;
                    }
                    elsif ($series_title &amp;&amp; $episode_title)
                    {
                        $filepath = &quot;$VIDEO_DIR/$series_title&quot;;
                        $filename = &quot;$filepath/$series_title - $episode_title&quot;;
                    }
                    elsif ($title)
                    {
                        $filepath = &quot;$VIDEO_DIR/$title&quot;;
                        $filename = &quot;$filepath/$title&quot;;
                    }
                    else
                    {
                        $filepath = &quot;$VIDEO_DIR&quot;;
                        $filename = &quot;$filepath/Unknown&quot;;
                    }
                    print &quot;OK\n&quot;;

                    unless (-d $filepath)
                    {
                        print &quot;Path $filepath doesn't exist, creating... &quot;;
                        mkdir($filepath);
                        if (-d $filepath)
                        {
                            print &quot;OK\n&quot;;
                        }
                        else
                        {
                            print &quot;FAIL\n&quot;;
                            exit;
                        }
                    }

                    # Get the video with curl
                    print &quot;Getting video... &quot;;
                    system(&quot;$CURL --digest -s -k -u $USER:$MAK -c /tmp/cookies.txt -o \&quot;$filename.tivo\&quot; \&quot;$video_url\&quot;&quot;);
                    if (-f &quot;$filename.tivo&quot;)
                    {
                        my $filesize = (stat(&quot;$filename.tivo&quot;))[7];

                        if ($filesize &gt; 0)
                        {
                            print &quot;OK\n&quot;;

                            # Convert to MPG
                            print &quot;Converting video to MPG format... &quot;;
                            system(&quot;$TIVODECODE -m $MAK -o \&quot;$filename.mpg\&quot; \&quot;$filename.tivo\&quot; &gt; /dev/null 2&gt;&amp;1&quot;);
                            if (-f &quot;$filename.mpg&quot;)
                            {
                                print &quot;OK\n&quot;;
                                unlink &quot;$filename.tivo&quot;;
                                open(OUT, &quot;&gt;&gt;$PROGRAMS_FILE&quot;);
                                print OUT &quot;$program_id\n&quot;;
                                close(OUT);
                            }
                            else
                            {
                                print &quot;FAIL\n&quot;;
                                exit();
                            }

                            # Output metadata file
                            print &quot;Outputting metadata... &quot;;
                            open (OUT, &quot;&gt;$filename.mpg.txt&quot;);

                            foreach my $key (keys %meta)
                            {
                                if ($meta{$key})
                                {
                                    if ($meta{$key} =~ /^ARRAY/)
                                    {
                                        foreach my $item (@{$meta{$key}})
                                        {
                                            unless ($item =~ /^HASH/)
                                            {
                                                print OUT &quot;$key : &quot; . fix_chars($item) . &quot;\n&quot;;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        unless ($item =~ /^HASH/)
                                        {
                                            if ($key eq &quot;originalAirDate&quot;)
                                            {
                                                print OUT &quot;$key : &quot; . $meta{$key} . &quot;\n&quot;;
                                            }
                                            else
                                            {
                                                print OUT &quot;$key : &quot; . fix_chars($meta{$key}) . &quot;\n&quot;;
                                            }
                                        }
                                    }
                                }
                            }
                            unlink($TMPFILE);
                            close(OUT);
                            print &quot;OK\n&quot;;
                        }
                        else
                        {
                            print &quot;FAIL\n&quot;;
                        }
                    }
                    else
                    {
                        print &quot;FAIL\n&quot;;
                        exit();
                    }
                }
                else
                {
                    print &quot;FAIL\n&quot;;
                    exit();
                }
            }
        }
    }
}

# Convert any offending characters
sub fix_chars($)
{
    my ($data) = @_;

    $data = unidecode($data);

    $data =~ s/\:/ -/g;
    $data =~ s/\//-/g;
    $data =~ s/\\/-/g;
    $data =~ s/\?/-/g;
    $data =~ s/\*/-/g;

    return $data;
}
</pre>
<p>Put the script wherever you want it &#8211; (I usually put my scripts into /usr/local/bin) &#8211; Edit the script, and fill in the $HOST, $MAK, and $VIDEO_DIR variables with the data gathered in step 1.  Then do a test run.  It will take a while to copy the data.  If it&#8217;s working fine, add to cron to have it copy the files regularly.  I copy mine at midnight:</p>
<p><code>0 0 * * * /usr/local/bin/tivo_dump >/dev/null 2>&#038;1</code></p>
<p>This says, run every day at midnight and send the output to /dev/null (otherwise you&#8217;ll get emails every day, which you may or may not want). </p>
<p>Note: Most of this script deals with metadata &#8211; it writes a text file (filename).txt with the metadata about the program, which is in pyTivo format.  For more info, see my <a href="http://www.edsalisbury.net/linux/how-to-set-up-a-tivo-media-server-on-ubuntu-linux/">guide</a> on how to set up pyTivo as a media server for TiVos.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.edsalisbury.net/linux/how-to-copy-videos-from-a-series-3-tivo-to-ubuntu-linux/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>How to Set Up a TiVo Media Server on Ubuntu Linux</title>
		<link>http://www.edsalisbury.net/linux/how-to-set-up-a-tivo-media-server-on-ubuntu-linux/</link>
		<comments>http://www.edsalisbury.net/linux/how-to-set-up-a-tivo-media-server-on-ubuntu-linux/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 20:40:40 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[TiVo]]></category>
		<category><![CDATA[Videos]]></category>
		<category><![CDATA[pytivo]]></category>

		<guid isPermaLink="false">http://www.edsfamily.com/ed/?p=97</guid>
		<description><![CDATA[
This guide will help you set up a media server to be able to play videos on your Series 3 TiVo, using pyTiVo.  (Note: this post was moved from my old blog, but has been updated a bit)
First, install ffmpeg:
$ sudo apt-get install ffmpeg
Then, install git (needed to grab pyTivo):
$ sudo apt-get install git-core
Then, [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.edsalisbury.net/wp-content/uploads/2009/07/tivo-logo1-134x150.jpg" alt="TiVo" title="TiVo" width="134" height="150" class="alignright size-thumbnail wp-image-298" /><br />
This guide will help you set up a media server to be able to play videos on your Series 3 TiVo, using pyTiVo.  (Note: this post was moved from my old blog, but has been updated a bit)</p>
<p>First, install ffmpeg:</p>
<pre>$ sudo apt-get install ffmpeg</pre>
<p>Then, install git (needed to grab pyTivo):</p>
<pre>$ sudo apt-get install git-core</pre>
<p>Then, grab the latest version of the pyTivo script (Look at the <a href="http://pytivo.armooo.net/wiki/CurrentRelease">Current Release</a> page to verify that you have the right version):</p>
<pre>$ cd /usr/share
$ sudo git clone git://repo.or.cz/pyTivo/wmcbrine.git
$ sudo mv wmcbrine pyTivo</pre>
<p>Edit /usr/share/pyTivo/pyTivo.conf:</p>
<pre>$ cd /usr/share/pyTivo
$ sudo cp pyTivo.conf.dist pyTivo.conf
$ sudo vi pyTivo.conf</pre>
<p>The only thing that I changed is to comment out the default video share, and add my own:</p>
<pre>[Movies]
type=video
path=/data/Video/Movies
[Television]
type=video
path=/data/Video/Television
[Music]
type=music
path=/data/Audio/Music</pre>
<p>Run pyTivo:</p>
<pre>$ sudo python /usr/share/pyTivo/pyTivo.py</pre>
<p>Verify that things are working correctly &#8212; on the Tivo, go to &#8220;Now Playing List&#8221; and look for the shares.  If they appear and you can browse to them, you&#8217;re almost done!</p>
<p>One issue I had was with transferring the videos.  When I transferred them to the TiVo, it had a message of &#8220;unknown mpeg2 codec&#8221; or something to that effect.  Apparently the package for ffmpeg on Intrepid doesn&#8217;t have all of the codecs needed.  To install them, run the following:</p>
<pre>$ sudo apt-get install libavcodec-unstripped-51</pre>
<p>After I did this, videos were able to be transferred just fine.</p>
<p>The last thing to do is to make pyTiVo start automatically on bootup.  To do this, simply copy the following script to /etc/init.d:</p>
<pre class="brush:bash; gutter: false; wrap-lines: true; ruler: false">
#!/bin/bash
# chkconfig: 2345 99 05
# description: pyTivo server

### INIT INFO
# Provides: pytivo
# Required-Start: $network
# Required-Stop: $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-description: pyTivo server
# Description: Start and stop the pyTivo server.
### END INIT INFO

RETVAL=0

start() {
echo -n "Starting pyTivo: "
pgrep -f pyTivo.py
RETVAL=$?
[ $RETVAL -eq 0 ] &#038;&#038; echo "pyTivo already running: Exiting" &#038;&#038; exit 1

# this call actually starts pyTivo.
python /usr/share/pyTivo/pyTivo.py > /dev/null 2>&#038;1 &#038;
RETVAL=$?
[ $RETVAL -eq 0 ] &#038;&#038; echo -n "done"
echo
return $RETVAL
}

stop() {
echo -n "Stopping pyTivo: "
pkill -f pyTivo.py
RETVAL=$?
echo
[ $RETVAL -eq 0 ] &#038;&#038; echo -n "done"
echo
return $RETVAL
}

# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
restart|reload)
stop
sleep 1
start
RETVAL=$?
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $RETVAL
</pre>
<p><em>Note: I didn&#8217;t write this &#8211; I just grabbed it from somewhere when setting it up &#8211; let me know if you wrote it so that I can give you credit!</em></p>
<p>After creating the script, make it executable:</p>
<pre>$ sudo chmod u+x /etc/init.d/pytivo</pre>
<p>Then create links to /etc/rc3.d and /etc/rc1.d:</p>
<pre>$ sudo ln -s /etc/init.d/pytivo /etc/rc3.d/S99pytivo
$ sudo ln -s /etc/init.d/pytivo /etc/rc1.d/K99pytivo
</pre>
<p>This should make it so that pytivo starts automatically upon bootup.</p>
<p>Hopefully you&#8217;ve found this guide useful.  Next time, I&#8217;ll be talking about how to make the videos show up perfectly on the TiVo, with appropriate titles, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.edsalisbury.net/linux/how-to-set-up-a-tivo-media-server-on-ubuntu-linux/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Converting TiVo MPEG2 Videos to H.264</title>
		<link>http://www.edsalisbury.net/linux/how-to-convert-tivo-mpeg2-videos-to-h264/</link>
		<comments>http://www.edsalisbury.net/linux/how-to-convert-tivo-mpeg2-videos-to-h264/#comments</comments>
		<pubDate>Thu, 07 May 2009 04:45:57 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[TiVo]]></category>
		<category><![CDATA[Videos]]></category>

		<guid isPermaLink="false">http://www.edsalisbury.net/?p=28</guid>
		<description><![CDATA[Something I&#8217;ve been working on a lot lately (and haven&#8217;t been posting until I had things the way I wanted them) was to convert my tivo mpeg2 files that I&#8217;ve been copying over from my S3 Tivo to something a little smaller, like h.264.  I have a script to do this, which I&#8217;ll provide, but [...]]]></description>
			<content:encoded><![CDATA[<p>Something I&#8217;ve been working on a lot lately (and haven&#8217;t been posting until I had things the way I wanted them) was to convert my tivo mpeg2 files that I&#8217;ve been copying over from my S3 Tivo to something a little smaller, like h.264.  I have a script to do this, which I&#8217;ll provide, but I&#8217;d like to go through the process, which consists of:</p>
<ol>
<li>Getting the dimensions of the video</li>
<li>Cropping letterbox and overscan</li>
<li>Encoding the video</li>
</ol>
<p>I had a *lot* of issues with AV Sync as well as dropped frames using HandBrake (that no one seemed to know why) so I went with mencoder.  I also left the audio as-is instead of transcoding into AAC.  It&#8217;s not a &#8220;proper&#8221; h.264 file with AC-3, but it works for my purposes.</p>
<p><span id="more-28"></span></p>
<p>First off, we need to figure out the dimensions of the video.  The reason is, we want to crop off the timecode/overscan line on the top of the video so that 1. it looks better, and 2. we can actually use cropdetect to figure out where the black bars are.   Here&#8217;s how to get video dimensions:</p>
<pre>mplayer -nojoystick -nolirc -vo null -ao null -identify -frames 0 $input</pre>
<p>The options I&#8217;m using:</p>
<ul>
<li>-nojoystick &#8211; prevents mplayer spewing out warnings about joysticks</li>
<li>-nolirc &#8211; same thing here &#8211; we&#8217;re not using LIRC, so don&#8217;t warn us</li>
<li>-vo null &#8211; No video output device</li>
<li>-ao null &#8211; No audio output device</li>
<li>-identify &#8211; Spit out the info</li>
<li>-frames 0 &#8211; We don&#8217;t need to actually look at any frames, so we set to 0</li>
<li>$input &#8211; The input file</li>
</ul>
<p>This will output quite a few interesting lines &#8212; the ones we care about are ID_VIDEO_WIDTH and ID_VIDEO_HEIGHT.  These tell us the dimensions of the video.</p>
<p>For the next step, we&#8217;re going to want to strip off the overscan line &#8212; to do this, we subtract 6 pixels from the height, (I&#8217;ll use a variable called $OVERSCAN) and then send that to mplayer again, this time to detect the crop area that we want:</p>
<pre>$height -= $OVERSCAN;
mplayer -nojoystick -nolirc -vo null -ao null -vf crop=$width:$height:0:$OVERSCAN,cropdetect -ss 600 -endpos 180 $input</pre>
<p>The new options here are:</p>
<ul>
<li>-vf crop &#8211; specify the crop area like this width:height:x:y &#8211; x and y are the starting position from the left/top &#8211; since we want to pre-crop off the overscan, we have to remove from height as well as start from that position.</li>
<li>cropdetect &#8211; This tells mplayer to spit out a line for every frame saying where it thinks you&#8217;ll want to crop the video</li>
<li>-ss 600 &#8211; This tells it to start 600 seconds into the video &#8211; I wanted to get the middle somewhere, just because the file could start with the end of the previous program, etc.</li>
<li>-endpos 180 &#8211; This says to stop 180 seconds after it starts (bad name in my opinion) &#8211; I want to grab 3 minutes worth of video, in case we happen to be in the middle of a commercial break</li>
</ul>
<p>This will spit out a ton of lines with crop info, and we want to grab the most common crop sizes.  To do this, I use some perl:</p>
<pre>foreach $line (@cropdetect)
{
    if ($line =~ /-vf crop=([\d:]+)/)
    {
        $croptest{$1}++;
    }
}

# Get the crop value with the most hits
my @croplist = sort { $croptest{$b} &lt;=&gt; $croptest{$a} } keys (%croptest);
my $crop = $croplist[0];</pre>
<p>This will grab the crop value that&#8217;s the most popular.  (The sort line brings it to the first element in the array)</p>
<p>Now that we know where we want to crop, we can begin encoding.  I use a 2-pass encoding method, which is the accepted standard for great quality encoding.  You can go with 1-pass or more than 2, but I think 2 is the sweet spot.  A lot of these options I&#8217;m not actually sure what they do, but will explain the ones that I do know about.</p>
<pre>mencoder -ovc x264 -x264encopts pass=1:turbo:bitrate=$VBITRATE:bframes=1:me=umh:partitions=all:trellis=1:qp_step=4:qcomp=0.7:direct_pred=auto:keyint=300 -vf pp=ci,crop=$crop,scale=-1:-10,harddup -oac copy -ofps 30000/1001 $input -o /dev/null</pre>
<p>Options:</p>
<ul>
<li> -ovc x264 &#8211; Use x264 for the Output Video Codec</li>
<li> -x264encopts &#8211; Specify options to pass to x264</li>
<li>pass=1 &#8211; 1st pass</li>
<li>bitrate=$VBITRATE &#8211; I set $VBITRATE to 1500 &#8211; which is 1500 kbits, you can go less for smaller files/lower quality</li>
<li>pp=ci &#8211; Deinterlacing &#8211; tivo files are interlaced, so I wanted to get rid of that</li>
<li>crop=$crop &#8211; use the crop value that we determined earlier</li>
<li>scale=-1:-10 &#8211; This will downscale the video so that it uses sizes divisible by 16 &#8211; there&#8217;s encoding and even playback issues if you don&#8217;t do this.  You can upscale by using -10:-1, but I didn&#8217;t really see the point in upscaling.</li>
<li>harddup &#8211; This means that you want to duplicate frame by frame (hard duplicate) &#8211; if you don&#8217;t, you&#8217;ll run into A/V sync issues</li>
<li>-oac copy &#8211; Audio is passthrough &#8211; don&#8217;t touch it</li>
<li>-ofps 30000/1001 &#8211; Hard sets the FPS to 29.97 &#8211; I didn&#8217;t want the frame rate to jump back and forth like it does, so I wanted to hard set this &#8211; haven&#8217;t found a good reason not to</li>
<li>-o /dev/null &#8211; The first pass will just log to a logfile, it won&#8217;t write to the output file</li>
</ul>
<p>After the first pass is done, we do another pass, which has almost the same parameters:</p>
<pre>mencoder -ovc x264 -x264encopts pass=2:turbo:bitrate=$VBITRATE:bframes=1:me=umh:partitions=all:trellis=1:qp_step=4:qcomp=0.7:direct_pred=auto:keyint=300 -vf pp=ci,crop=$crop,scale=-1:-10:,harddup -oac copy -ofps 30000/1001 $input -o $output</pre>
<p>New options:</p>
<ul>
<li>pass=2 &#8211; 2nd pass</li>
<li>-o $output &#8211; this time output to our output file</li>
</ul>
<p>When this is completed, you should have a video file with h.264 for the video, and AC3 for the audio.  This resulted in file sizes at about 60% of the originals, which is good enough for me.  I hope someone found this useful.  I&#8217;ll be putting up a script soon that will do all of this work for you (and even work from a queue), but till then, I wanted to get the details out there.</p>
<p>Update: I have created another guide that includes the script that I use <a href="http://www.edsalisbury.net/linux/how-to-convert-dvds-and-tivo-mpeg2-videos-to-h-264/">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.edsalisbury.net/linux/how-to-convert-tivo-mpeg2-videos-to-h264/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
