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; }
June 29th, 2003 at 7:58 am
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!!!
August 2nd, 2003 at 7:57 pm
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
August 5th, 2003 at 8:53 am
Yes.
This script is really cool, thanks allot
Is there a possiblity to get all available channels first and create a playlist for each ?
August 9th, 2003 at 2:17 pm
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”;
}
August 27th, 2003 at 2:33 pm
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
October 12th, 2003 at 6:35 am
Wow. This is the blog I was looking for…
February 13th, 2005 at 8:16 am
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!
May 21st, 2005 at 9:19 pm
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