Hack 86 Robot Karaoke

Hack 86 Robot Karaoke

figs/moderate.gif figs/hack86.gif

Who says people get to have all the fun? With this hack, you can let your computer do a little singing , by scraping the LyricsFreak.com web site and sending the results to a text-to-speech translator .

There are things that are text-only and things that are multimedia. Then there's this hack, which turns boring old text into multimediaspecifically, a .wav file.

This hack, as it stands, is actually pretty silly. It searches the lyric collections at LyricsFreak.com for the keywords you specify, then sends the matching lyrics to yet another site (http://naturalvoices.com) that turns them into a .wav file. If you're running a Win32 system, the code will then automatically play the .wav file ("sing" the lyrics, for some narrow definition of sing ) via the Win32::Sound module (http://search.cpan.org/author/ACALPINI/Win32-Sound/).

Listening to your computer's rendition of the Spider-Man theme song can be detrimental to your health.


As you're playing with this code, you might want to think of more sublime and less ridiculous implementations . Do you have a site read by low-vision people? Are there short bits of text, such as a local weather forecast, that would be useful for them to have read aloud ? Would it be helpful to have a button that would convert a story summary to a .wav file for later download?

The Code

One of the modules used with this code, Win32::Sound , is for Win32 machines only. Since it's used to play back the generated .wav file, you will not get a "singing" robot if you're on a non-Win32 machine; you'll just get a .wav file, suitable for playing through your preferred music player.

Save this script as robotkaroake.pl :

 #!/usr/bin/perl -w use strict; use LWP::Simple; use URI::Escape; use Win32::Sound; use SOAP::Lite; # use your own Google API key here! my $google_key  = "   your Google key here   "; my $google_wdsl = "GoogleSearch.wsdl"; # load in our lyrics phrase from the command line. my $lyrics_phrase = shift or die "Usage: robot-karaoke.pl <phrase>\n"; # and perform the search on Google. my $google_search_term = "intitle:\"$lyrics_phrase\" site:lyricsfreak.com"; my $googleSearch = SOAP::Lite->service("file:$google_wdsl"); my $result = $googleSearch->doGoogleSearch(                       $google_key, $google_search_term,                       0, 10, "false", "", "false",                       "", "", ""); # if there are no matches, then say so and die. die "No LyricsFreak matches were found for '$lyrics_phrase'.\n"           if $result->{estimatedTotalResultsCount} == 0;    # and take the first Google result as # the most likely location on LyricsFreak.com. my @results         = @{$result->{'resultElements'}}; my $first_result    = $results[0]; my $lyricsfreak_url = $first_result->{'URL'}; print "Downloading lyrics from:\n $lyricsfreak_url\n"; # and download the data from LyricsFreak.com. my $content = get($lyricsfreak_url) or die $!; print "Connection to LyricsFreak was successful.\n"; # we have the data, so let's parse it. # all lyrics are stored in a pre tag, # so we delete everything before and after. $content =~ s/.*<pre><b>.*<\/b><br>//mgis; $content =~ s/<\/pre>.*//mgis; my @lyrics_lines = split("\x0d", $content); # AT&T's demo TTS service takes a maximum of 30 words, # so we'll create a mini chunk of the lyrics to send off. # each of these chunks will be sent to the TTS server # then saved seperately as multiple mini-wav files. my (@lyrics_chunks, $current_lyrics_chunk); my $line_counter = 0; for (my $i = 0; $i <= scalar(@lyrics_lines) - 1; ++$i) {     next if $lyrics_lines[$i] =~ /^\s*$/;     $current_lyrics_chunk .= $lyrics_lines[$i] . "\n";     if (($line_counter == 5)  ($i == scalar(@lyrics_lines) - 1) ) {         push(@lyrics_chunks, $current_lyrics_chunk);         $current_lyrics_chunk = ''; $line_counter = 0;     } $line_counter++; } # now, we'll go through each chunk, # and send it off to our TTS server. my @temporary_wav_files; foreach my $lyrics_chunk (@lyrics_chunks) {     # and download the data.     my $url = 'http://morrissey.naturalvoices.com/tts/cgi-bin/nph-talk';     my $req = HTTP::Request->new('POST', $url); # almost there!     $req->content('txt=' . uri_escape($lyrics_chunk) .                   '&voice=crystal&speakButton=SPEAK');     $req->content_type('application/x-www-form-urlencoded');     my $res = LWP::UserAgent->new->simple_request($req);     # incorrect server response? then die.     unless ($res->is_success  $res->code == 301) {        die "Error connecting to TTS server: " . $res->status_line . ".\n"; }     # didn't get the response we wanted? die.     if ($res->content !~ /can be found <A HREF=([^>]*)>here<\/A>/i) {        die "Response from TTS server not understood. Odd.\n"; }     # side effect of error checking above is to set  to     # the actual wav file that was generated. this is good.     my $wav_url  = "http://morrissey.naturalvoices.com";     my $wav_file = ; # for use in saving to disk.     $wav_file =~ s/.*?\/(\w+.wav)//;     getstore($wav_url, "$wav_file") or      die "Download of $wav_file failed: $!";     push(@temporary_wav_files, $wav_file); } # with all our files downloaded, play them in # order with the Win32::Sound module. else, they # just sit there in hopes of the user playing them. print  "Playing downloaded wav files...\n"; foreach my $temporary_wav_file (@temporary_wav_files) {     print " Now Playing: $temporary_wav_file\n";     Win32::Sound::Play("$temporary_wav_file"); 

}

Running the Hack

Invoke the script on the command line, passing it the phrase you're interested in; the script will search for that phrase in the titles of pages on LyrisFreak.com. If it doesn't find the phase, it'll just stop:

 %  perl robotkaroake.pl "fish heads"  No LyricsFreak matches were found for 'fish heads'. 

If it does find the phrase, it'll download the lyrics and generate the .wav file:

 %  perl robotkaroake.pl "born never asked"  Downloading lyrics from:  http://www.lyricsfreak.com/l/laurie-anderson/81556.html Connection to LyricsFreak was successful. Playing downloaded wav files...  Now Playing: 7a0c0093f2f531ac98691152d1f74367.wav 

The previous example shows the output of a rather short entry. Longer songs will result in more .wav files saved to the current directory, each representing a small chunk (a single chunk representing one request to the TTS server):

 %  perl robotkaroake.pl "under the moon"  Downloading lyrics from:  http://www.lyricsfreak.com/i/insane-clown-posse/67657.html Connection to LyricsFreak was successful. Playing downloaded wav files...  Now Playing: fe34e081ab8a3abaeecdb1e50b030209.wav  Now Playing: 80709499765f9bfe75d3c7234c435a79.wav  Now Playing: f1ca99233f9cdc6a78f311db887914f1.wav  Now Playing: fd6b61421f3fc56510cf4b9e0d3a0e12.wav  Now Playing: b954f58f906d53ec312bbcc6579ebe12.wav  Now Playing: 407415e685260754174cf45338ba4d10.wav  Now Playing: 8a2ade6e7f8fe950ddcb58747d241694.wav  Now Playing: 22ed038190b9ed0fb4e3077655503422.wav 


Spidering Hacks
Spidering Hacks
ISBN: 0596005776
EAN: 2147483647
Year: 2005
Pages: 157

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net