1

I want to display a type of audio (mp3, ogg, aac e.t.c) while a Web radio station playing. My player code is simple in briefly:

let audio = new Audio;
audio.addEventListener('loadeddata', () => audio.play());
audio.src = 'https://some-radio-station.com/stream';

I found no way to get file or HTTP response metadata using web audio API. May be is possible to load a short part of stream using fetch?

By the way is there a method to detect audio bitrate too?

Mik
  • 374
  • 2
  • 13
  • You can easily obtain that infos with `ffprobe`, but this requires server side code. – pierpy Jul 20 '23 at 05:30
  • I found acceptable solution wth HTTP headers but I'm not sure it is good enough to publicate as answer. May be I will post it after some experiments and improvements. However you suggest a very good idea, to seek some WASM modules can test binary data. You mean https://github.com/tfoxy/ffprobe-wasm , this module requires a server side too? – Mik Jul 20 '23 at 21:06

2 Answers2

1

The way I could make work:

//module
function ObtainStreamHeaders(src) {
  return new Promise((resolve, reject) => {
    const controller = new AbortController;
    fetch(src, {signal: controller.signal})
      .then(response => {
        controller.abort();
        let headers = {};
        for (var pair of response.headers.entries()) {
          headers[pair[0]] = pair[1];
        }
        resolve(headers);
      })
      .catch(e => reject(e));
  });
}
export default ObtainStreamHeaders;
//using
import ObtainStreamHeaders from './ObtainStreamHeaders.js';
audio.onplaying = () => ObtainStreamHeaders(audio.src)
      .then(headers => {
        document.getElementById('mime').innerText = 
          headers['content-type'] || 'unknown';
        document.getElementById('br').innerText = headers['icy-br'] ? 
          (parseInt(headers['icy-br'], 10) + 'kbps') : 'unknown';
      });

This code downloads a small part of an audio stream and gets server headers

Mik
  • 374
  • 2
  • 13
  • I think that this actually issues two requests to the server, one for the audio element, then another one just to get the headers..,Am I understanding this correctly? This would put a "double" load on the server. – Marcel Aug 22 '23 at 05:13
  • Yes, right. But second request downloads just a small part of stream before downloading stopped by abort signal. – Mik Aug 25 '23 at 08:03
  • I remember that you could try to fetch the headers only, using this method: https://stackoverflow.com/questions/47240975/how-to-fetch-using-fetch-api-only-headers-in-javascript-not-the-whole-content I make this an answer, because it is – Marcel Aug 25 '23 at 13:26
0

You could issue a second request, as you already propose. It's actually possible to get the headers only, keeping server load low, even with the Fetch API itself. See this existing answer: https://stackoverflow.com/a/47241400/79485

fetch(url, {method: 'HEAD'})

Then extract the content-type header to get the, well, content type.

To get other metadata of the media file / stream itself, you still would need to get actual content. Not all media formats provide the same metadata, and in the same format. You would need to handle each format separately.

Cheat

If you, however, are only interested in approximate bitrates, and know the duration of your sound (given it's already loaded in the audio element), and the headers provide an content-length info, you can calculate the raw bitrate like this: https://stackoverflow.com/a/21663002/79485. It's already been done here: https://stackoverflow.com/a/11587642/79485

Marcel
  • 15,039
  • 20
  • 92
  • 150
  • Success of `HEAD` request depends on third-party server settings, such kind of requests just not work very often. So "partial `GET`" still more effective in practice. – Mik Aug 27 '23 at 20:42
  • There's an only way I did not try: access to raw data via Media Source Extensions API. It may be allows to avoid double requests but requires to rewrite the whole playback logic – Mik Aug 27 '23 at 20:50
  • @Mik I did now know about Media Source Extension yet. Thanks for mentioning it. It's interesting, but it seems not to be the preferred tool for just getting the mime type or bitrate. – Marcel Aug 28 '23 at 05:19