Hey guys. I've been using this script for years to find the URL so that I can use wget to grab streams:
Code:
#!/usr/bin/env python
from random import choice
import os
import sys
import urllib2
import xml.dom.minidom as minidom
def validate_callsign(cs):
'''
Normal callsign format is 'WWWWFFAAA', where 'WWWW' is the radio station
callsign, 'FF' is either 'AM' or 'FM', and 'AAA' is always 'AAC'.
For this function, we expect the 'WWWWFF' part as input.
'''
if not cs or not isinstance(cs, str):
raise ValueError('callsign \'%s\' is not a string.' % cs)
if len(cs) < 6:
raise ValueError('callsign \'%s\' is too short.' % cs)
if not cs.endswith('AAC'):
cs = cs + 'AAC'
band = cs[-5:-3]
if band != 'AM' and band != 'FM':
raise ValueError('callsign \'%s\' is missing \'FM\' or \'AM\'.' % cs)
return cs
def make_request(callsign):
host = 'playerservices.streamtheworld.com'
req = urllib2.Request(
'http://%s/api/livestream?version=1.2&mount=%s&lang=en' %
(host, callsign))
req.add_header('User-Agent', 'Mozilla/5.0')
return req
def t(element):
'''get the text of a DOM element'''
return element.firstChild.data
def check_status(ele):
# should only be one status element inside a mountpoint
status = ele.getElementsByTagName('status')[0]
if t(status.getElementsByTagName('status-code')[0]) != '200':
msg = t(status.getElementsByTagName('status-message')[0])
raise Exception('Error locating stream: ' + msg)
def create_stream_urls(srcfile):
doc = minidom.parse(srcfile)
mp = doc.getElementsByTagName('mountpoint')[0]
check_status(mp)
mt = t(mp.getElementsByTagName('mount')[0])
allurls = []
for s in mp.getElementsByTagName('server'):
# a thing of beauty, right?
ip = t(s.getElementsByTagName('ip')[0])
ports = [t(p) for p in s.getElementsByTagName('port')]
# yes, it is always HTTP. We see ports 80, 443, and 3690 usually
urls = ['http://%s:%s/%s' % (ip, p, mt) for p in ports]
allurls.extend(urls)
return allurls
def start_mplayer(location):
print location
return os.system('mplayer %s' % location)
if __name__ == '__main__':
if len(sys.argv) < 2:
print 'usage: station callsign must be the first argument'
sys.exit(1)
callsign = validate_callsign(sys.argv[1])
req = make_request(callsign)
result = urllib2.urlopen(req)
urls = create_stream_urls(result)
if len(urls) > 0:
u = choice(urls)
sys.exit(start_mplayer(u))
sys.exit(1)
This has worked great for MANY years. Suddenly it seems that some stations are changing their URLs on every request. Here's an example with commands issued within a few seconds of each other:
Code:
root@debian# python streamtheworld.py KPELAMAAC
http://14133.live.streamtheworld.com:3690/KPELAMAAC
( /mnt/data/data/radio/bin )
root@debian# python streamtheworld.py KPELAMAAC
http://13733.live.streamtheworld.com:3690/KPELAMAAC
( /mnt/data/data/radio/bin )
root@debian# python streamtheworld.py KPELAMAAC
http://14213.live.streamtheworld.com:80/KPELAMAAC
Does anyone know of a good way around this or do I need to look at a different stream capture method? Is there something decent for Linux?
Many thanks!