Apr 15 2003

Oh my – now the TV is speaking to me ..

A few days ago (see: TiVo + Home Media Option + EMail) we went through a little exercise to have the TiVo (with Home Media Option installed) display “images” for all current emails on a POP3 server. This worked fine and was a nice little hack.

Now let’s take that concept to another level.

Besides images, the Home Media Option also allows to send MP3 files from your PC to the TiVo unit – right?

Well, I changed the script from the message referenced above to use the Microsoft Speech Object Library (version 5.0; which was installed on my Windows XP Professional system) to “render” the first few lines (PREVIEW_LINES) of each email to a temporary WAV file. After the email has been “recorded” in the WAV file I use a command-line WAV to MP3 converter to turn the file into a file the TiVo unit can understand. If we create the file successully, we moved it into an area that can be “seen” by the TiVo Media Desktop (D:\MP3\TiVo).

Besides perl (see: http://www.activestate.com/Products/ActivePerl/), you will need the Microsoft Spech Object Library on your system and you will need access to a command line MP3 encoder. I’ve picked “bladeenc” for this purpose. You will need to google it or use a different mp3 encoder. The line were the encoder is called, is marked in italic below.

And here is the script that does it all:

#!c:\perl\bin\perl.exe

use strict;
use Cwd;
use File::Copy;
use File::Path;
use File::Spec;
use Mail::POP3Client;
use Mail::Internet;
use LWP::Simple;
use Win32;
use Win32::OLE;
use Win32::OLE::Const qq{Microsoft Speech Object Library};

use constant DESTINATION   => q{D:\MP3\TiVo};
use constant PREVIEW_LINES => 30;

my @accounts = (
    {
     DESC      => q{thoellri@foobar.com},
     USER      => "thoellri",
     AUTH_MODE => "PASS",
     PASSWORD  => "password",
     HOST      => "pop3.foobar.com"
    },
    {
     DESC      => q{tobias@somewhere.com},
     USER      => "tobias",
     AUTH_MODE => "PASS",
     PASSWORD  => "password",
     HOST      => "mail.somewhere.com"
    },
);

for my $account (@accounts) {
    # erase existing messages
    rmtree([ File::Spec->catfile(DESTINATION, qq{Email}, $account->{DESC}) ], 0, 0);
    my $pop = new Mail::POP3Client (%$account);
    unless ($pop) { warn "Couldn't connect\n"; next; }
    my $count = $pop->Count;
    if ($count <0) { warn "Authorization failed"; next; }
    next if($count == 0); # no new messages
    # create new directory for messages
    mkpath([ File::Spec->catfile(DESTINATION, qq{Email}, $account->{DESC}) ], 0, 0711);
    for my $num (1..$count) {
	my @preview=$pop->HeadAndBody($num,100);
	my $mail=Mail::Internet->new(\@preview);
	my $mp3file=mail2mp3($mail);
	next unless defined($mp3file);
	my $out=File::Spec->catfile(DESTINATION, qq{Email}, $account->{DESC},
				    qq{message-}.sprintf("%02d",$num).qq{.mp3});
	copy($mp3file,$out);
	unlink($mp3file);
    }
    $pop->Close;
}

sub mail2mp3 {
    my($m)=@_;
    my $header=$m->head();

    my $type=Win32::OLE->new('SAPI.SpAudioFormat');
    $type->{Type}=SAFT32kHz16BitMono;
    my $stream=Win32::OLE->new('SAPI.SpFileStream');
    $stream->{Format}=$type;
    $stream->Open("output$$.wav",SSFMCreateForWrite,undef);
    my $speech=Win32::OLE->new('SAPI.SpVoice');
    $speech->{AudioOutputStream}=$stream;
    $speech->Speak(qq{From: }.$header->get('From'),SVSFDefault);
    $speech->Speak(qq{Subject: }.$header->get('Subject'),SVSFDefault);
    my($lines);
    foreach my $line (@{$m->body()}) {
	chomp($line);
	$speech->Speak($line." ",SVSFDefault);
	last if($lines++ >= PREVIEW_LINES);
    }
    $speech->WaitUntilDone(-1);
    $stream->Close();
    return undef unless (-f "output$$.wav");



    # here we call out to the command line mp3 encode
    system(qq{bladeenc -quiet -nocfg -quit output$$.wav output$$.mp3});



    unlink(qq{output$$.wav});
    return undef unless (-f "output$$.mp3");
    return File::Spec->catfile(getcwd,qq{output$$.mp3});
}

Again, let me know if you have questions about this stuff …

2 Responses to “Oh my – now the TV is speaking to me ..”

  • a friend of jouke Says:

    You could’ve saved yourself some trouble
    if you were smart and used CPAN ;)

    use Win32::MSAgent;

    http://search.cpan.org/author/JOUKE/Win32-MSAgent/

  • Tobias Hoellrich Says:

    I am smart and I did use CPAN and I did look at Win32::MSAgent, but did not find an obvious way to generate a 32KHz/16Bit WAV output instead of listening to the spoken words. Instead of installing Win32::MSAgent, trying to understand the source, modifying it and then only using 5% of it’s functionality, I decided to just code the 20 lines that do what I want them to do.

    Thanks “friend of jouke” …

Leave a Reply