For anyone else finding themselves here, 10 years later, here is the python3 version of @dbogdan's code. It may be notable that content[metaint:].split("'")[1]
is extremely unreliable. Also, as soon as you come across "Queensrÿche", a non-english title, etc... the title is going to be full of bytes where the special characters are. You can't decode
the entire tag, so there is a little bit of "jumping through hoops" to whittle the tag down to only a title. I did not grab sample rate
and bitrate
from the response headers because, they are constantly wrong. Get that data from the MP3 head. To be fair, the tag Shoutcast/Icecast gives you can be wrong in every way! It only takes one time of coming across "C C Revival - I hearded through the grapevine" (which really happened) to realize there is nothing official or reliable about these tags. This can create huge problems if, for instance: you use Shout/Ice cast tags as search parameters for MusicBrainz searches.
from urllib import request as urequest
import re
SRCHTITLE = re.compile(br'StreamTitle=\\*(?P<title>[^;]*);').search
def get_stream_title(tag:bytes) -> str:
title = ''
if m := SRCHTITLE(tag):
#decode, strip, unescape and remove surrounding quotes (may not even be the same type of quote)
title = m.group('title').decode('utf-8').strip().replace('\\', '')[1:-1]
return title
def id3(url:str) -> dict:
request = urequest.Request(url, headers={'Icy-MetaData': 1})
with urequest.urlopen(request) as resp:
metaint = int(resp.headers.get('icy-metaint', '-1'))
if metaint<0: return False
resp.read(metaint) #this isn't seekable so, arbitrarily read to the point we want
tagdata = dict(
site_url = resp.headers.get('icy-url' ) ,
name = resp.headers.get('icy-name' ).title(),
genre = resp.headers.get('icy-genre').title(),
title = get_stream_title(resp.read(255)) )
return tagdata