WAIT OMG I ACTUALLY DID IT!!
Apparently, the metadata is just stored as ASCII inside the stream, so literally I just set up a loop to continuously retrieve data from the server, regex it for "StreamTitle", then saved that to a string!!
Note: IDK if it's just the server I'm using, but it does seem to only send the StreamTitle tag when you first connect and when the song changes, so you will have to be careful with that. Also, it seems to always output a StreamTitle of <empty string> when you first connect, tho that gets updated in a few seconds.
Also, this doesn't actually play the stream, you'll have to get a seperate <audio> tag to do that. I could probably figure out how to stream the data to an audio tag manually, but that would be infinitely harder.
code:
async function readConstant(readableStream) {
const reader = readableStream.getReader();
const re = /StreamTitle='(.*)'/;
while (true) {
const { done, value } = await reader.read();
if (done) { break; }
// data is retrieved as a uint8 array, which we convert to str
let cur = new TextDecoder("utf-8").decode(value);
var fin = re.exec(cur);
if (!fin) { continue; }
// for some reason, the regex sometimes captures some unprintable chars after the end so we split on the single quote
fin = fin[1].split('\'')[0];
console.log(fin);
document.getElementById("player-text").innerHTML = fin;
}
}
var opts = { headers: {} };
opts["headers"]["Icy-MetaData"] = "1";
// this is the 64kbps version to save some bandwidth
let mustr = fetch("https://radio.erb.pw/listen/subspace/radio-64.mp3", opts);
mustr.then((res) => { readConstant(res.body) });