Apr 14 2003

Endless Source of live streams for TiVo

I started playing around with MP3 live streams from the Internet and found an interesting thread at http://www.tivocommunity.com/tivo-vb/showthread.php?s=&threadid=110606, which detailed the format of the .m3u files to have the TiVo unit recognize and play live streams.
There seems to be a requirement that URLs for live-streams must not have a path, but just consist of a host:port portion.
It was posted in the same thread how to get to those type of links, which involves a lot of trial-and-error.

Decided to use perl again as for the other TiVo projects (Beacon Watcher and Email Renderer). This time we ask www.shoutcast.com to help us out with the generation of .m3u files for the TiVo unit.

Let’s say I share out the path c:\tivo\mp3\ with my HMO “Music” option on the TiVo. Let’s also say that I want the top 15 Punk (just picked that for no particular reason) stations from shoutcast served through the location above. I would type the following on the PC that hosts the TiVo Media Server:

perl m3ugen.pl Punk 15 c:\tivo\mp3\Punk.m3u

This will go to www.shoucast.com, look up the category “Punk”, extract the top 15 playlists for Punk-stations, download each individual playlists, find TiVo-compatible server-entries and generate a Punk.m3u file in c:\tivo\mp3.
After doing this you would be able to go to the “Music and Photos” section of your HMO-enabled TiVo and find a “Punk.m3u” section under Music, which will show you up to 15 stations (I say “up to”, because some may not offer servers with TiVo-compatible format).

Here’s the list that was generated a few seconds ago (trimmed the length of entries):

#EXTM3U
#EXTINF:,(#1 - 15/100) idobi Radio: Music that doesn't suck!
http://66.227.96.189:5046
#EXTINF:,(#1 - 35/70) RADIO ELECTRACKS .: best tunes only
http://64.202.98.33:6390
#EXTINF:,(#1 - 20/100) Radio That Doesn't Suck
http://209.142.3.9:8100
#EXTINF:,(#1 - 20/50) #Punkrockers Oi! Oi! Oi!: serAphim onAir
http://80.67.228.169:8003
#EXTINF:,(#1 - 14/128) radio.punkmac.com -=- we dont play crap
http://66.227.110.18
#EXTINF:,(#1 - 11/20) Dr. Yo - the perfect prescription
http://64.202.98.33:6020
#EXTINF:,(#1 - 6/64) Dashnine Radio: Apathy is a cool emotion
http://38.210.43.154:8000
#EXTINF:,(#1 - 4/25) ReDDeR2k RaDiO
http://216.127.90.185:9860
#EXTINF:,(#1 - 5/300) All Ages Show -- High Bitrate
http://205.188.234.35:8078
#EXTINF:,(#1 - 2/32) k-storm radio
http://80.0.115.56:8000
#EXTINF:,(#1 - 1/100) (( SoCal P.I.S.S. )) (( where every
http://207.182.239.62:8000
#EXTINF:,(#1 - 4/50) BEYOND THE BEAT GENERATION
http://64.202.98.38:2720
#EXTINF:,(#1 - 3/25) Electrobleep.com Radio --)
http://66.227.96.189:5388
#EXTINF:,(#1 - 2/12) Butthole Radio
http://67.124.196.20:8002
#EXTINF:,(#1 - 2/10) SonicBlaze: Indie, Punk, Emo, and Ska
http://66.250.32.196:8006

Cool – isn’t it? You can request up to 25 results (and I do that to limit the traffic generated on shoutcast.com) and request quite a bunch of genres. To see the complete list, go to http://www.shoutcast.com and select “–Choose a genre –” on the right hand side. After selecting one, the page will refresh and you will see a URL that says http://www.shoutcast.com/directory/?sgenre= – the word that appears after the equal-sign is the same one the perl-script will expect on the command line.

And here’s the script in case you’re interested. As before, all missing modules can be downloaded via ppm. Just copy & paste the code below into a file called m3ugen.pl. You must have a direct internet connection on the system where you run this script. If you have a proxy-server in your network, you will need to set the HTTP_PROXY environment variable to point to your proxy-server.
Have fun and let me know if it works for you as well.

#!c:\perl\bin\perl.exe
use strict;
use HTML::LinkExtor;
use LWP::Simple;
use URI::URL;
use constant PROVIDER  => qq{http://www.shoutcast.com/};
use constant DIRECTORY => PROVIDER.qq{directory/};
my $genre=$ARGV[0];
my $results=$ARGV[1];
my $outfile=$ARGV[2];
unless (defined($genre) &&
	defined($results) && $results && $results <= 25 &&
        defined($outfile)) {
    die qq{Usage:\t$0 [genre] [numresults] [outfile]\n}.
      qq{\tgenre=TopTen,House,Blues,Punk,...\n}.
      qq{\tnumresults=1..25\n}.
      qq{\toutfile=m3u output file\n};
}
my @playlists=getPlaylists(DIRECTORY.qq{?sgenre=$genre&numresult=$results},PROVIDER);
unless (scalar(@playlists)) {
    die "No results found - unable to create playlist\n";
    exit(0);
}
@playlists=mapForTiVo(@playlists);
open(OUT,">".$outfile) or die "Unable to create output file - $!";
print OUT qq{#EXTM3U\n};
foreach my $entry (@playlists) {
    my($url,$title)=%$entry;
    print OUT qq{#EXTINF:,$title\n$url\n};
}
close(OUT);
sub getPlaylists {
    my($url,$base)=@_;
    my(@results);
    my $content=get($url);
    unless (defined($content) && length($content)) {
	warn qq{Unable to fetch "$url"\n};
	return @results;
    }
    my $parser=HTML::LinkExtor->new(sub {my($t,%a)=@_;
					 return if $t ne 'a';
					 push(@results,$a{href})
					   if($a{href}=~/filename\.pls$/i);});
    $parser->parse($content);
    @results = map {$_=url($_,$base)->abs;} @results;
    return @results;
}
sub mapForTiVo {
    my(@list)=@_;
    my(@results);
    foreach my $url (@list) {
	my $content=get($url);
	next unless(defined($content) && length($content));
	my($file);
	foreach my $line (split(/[\n\r]/,$content)) {
	    if ($line =~ /^File\d+=(.*)$/i) {
		my $u=URI::URL->new($1);
		$u->path(""),$file=$u->abs if($u->path eq '/' || $u->path eq '');
	    } elsif ($line =~ /^Title\d+\s*=(.*)$/i  && defined($file)) {
		push(@results,{$file => $1});
		last;
	    }
	}
    }
    return @results;
}

8 Responses to “Endless Source of live streams for TiVo”

  • gordho Says:

    found a link on the tivo community forums for this script and it saves me sooooo much time. i really have no programing experience but all I had to do was install activestate perl on my xp box and run the script. thanks!!!

  • Sm0kes Says:

    Oh… this rocks.

    I got it running no problem. I went ahead and scripted up a batch script that will autopopulate my stations every day.

    Thank you so much!

    SM0KES

  • mandy Says:

    Yes.

    This script is really cool, thanks allot
    Is there a possiblity to get all available channels first and create a playlist for each ?

  • Circeus Says:

    Hey. I just wanted to let you know how cool this is. I made a slight mod to it that does two things:

    1) Gives me a little feedback about what its adding.

    2) Pops off those “(#1 – 500)” strings at the front of the titles for the stations.

    Original looks like this:

    foreach my $entry (@playlists) {
    my($url,$title)=%$entry;
    print OUT qq{#EXTINF:,$title\n$url\n};
    }

    My mods make that look like this:

    foreach my $entry (@playlists) {
    print “\n”;
    my($url,$title)=%$entry;
    my $pos = index($title, ‘)’) + 2;
    my $realtitle = substr($title,$pos);
    print “$realtitle\n$url\n”;
    print OUT qq{#EXTINF:,$realtitle\n$url\n};
    print “\n”;
    }

  • sean Says:

    exellent..worked like a charm and i added that dudes mod as well.
    just annoying that some sites playing techno seem to make it to all the lists!!

    grrrrrrrrr

  • dns Says:

    Wow. This is the blog I was looking for…

  • duker Says:

    I’m not much of a programmer. When and where do you type: perl m3ugen.pl Punk 15 c:\tivo\mp3\Punk.m3u . How do I create the m3ugen.pl file. HELP!

  • Jason Says:

    Works great, but when the info screen comes up on the Tivo for the music info (ie. name,type,length) my computer errors a TivoServer abnormal error and shuts down the service. I have the series 2 with all updates

Leave a Reply