So basically i'm trying to get the currently playing track from online radio direct link (Example - http://air.radiorecord.ru:8101/rr_320).
Firstly i found something in the internet, written with urllib, my application is asynchronous so i needed to use aiohttp. With urllib it worked perfectly, while aiohttp sometimes just can't find anything. Pls help :(
before:
def get_now(self, session):
request = urllib.Request(self.data.get('url'),headers={'Icy-MetaData': 1} ) # request metadata
response = urllib.urlopen(request)
metadata = response.headers
metaint = int(response.headers['icy-metaint'])
for _ in range(10): # title may be empty initially, try several times
response.read(metaint) # skip to metadata
metadata_length = struct.unpack('B', response.read(1))[0] * 16 # length byte
metadata = response.read(metadata_length).rstrip(b'\0')
# extract title from the metadata
m = re.search(br"StreamTitle='([^']*)';", metadata)
if m:
title = m.group(1)
if title:
break
else:
return "No title found"
return title.decode('utf8', errors='replace')
except:
return "No title found"
after:
async def get_now(self, session):
async with session.get(self.stream_url, headers={'Icy-MetaData': "1"}) as resp:
content = resp.content
metadata = resp.headers
metaint = int(metadata['icy-metaint'])
for _ in range(30):
await content.read(metaint)
metadata_length = struct.unpack('B', await content.read(1))[0] * 16 # length byte
metadata = (await content.read(metadata_length)).rstrip(b'\0')
m = re.search(br"StreamTitle='([^']*)';", metadata)
if m:
title = m.group(1)
if title:
return title.decode('utf8', errors='replace')
else:
return "No title found"
return "Nothing found"
The snippet below is always able to detect the current track (in around 400ms) but instead of processing only part of the chunk it checks the whole chunk as it's read:
import aiohttp
import asyncio
import re
async def get_now(stream_url, session):
headers={"Icy-MetaData": "1"}
async with session.get(stream_url, headers=headers) as resp:
for _ in range(10):
data = await resp.content.read(8192)
m = re.search(br"StreamTitle='([^']*)';", data.rstrip(b"\0"))
if m:
title = m.group(1)
if title:
return title.decode("utf8", errors="replace")
else:
return "No title found"
return "Nothing found"
async def get_track():
session = aiohttp.ClientSession()
stream_url = "http://air.radiorecord.ru:8101/rr_320"
result = await get_now(stream_url, session)
print(f"result: {result}")
await session.close()
asyncio.run(get_track())
Result on my computer (CPU usage is very low on a quite old CPU: i7-3517U):
[ionut@ionut-pc ~]$ time python test.py
result: Record Club - Nejtrino & Baur
real 0m0.401s
user 0m0.198s
sys 0m0.031s