6

I'm trying to play an audio file using html5 audio tag.

It plays fine...

But for some reason it is required that the request browser is making for the source, must include a specific header that the browser (safari in my case) is not adding. (where as I see chrome adds)

The header is: Accept-encoding: gzip

How can I make this happen?

I do not want to download entire file beforehand... I want audio tag to handle it, with a new header.

document.getElementById("audio").load();
document.getElementById("audio").play();
<audio id="audio" src="https://upload.wikimedia.org/wikipedia/commons/transcoded/7/7b/FurElise.ogg/FurElise.ogg.mp3"> <audio>
    

Once again, when this code runs, I just want to modify header for every request made for this...

Note:

When you add a source and load in let's say chrome, the browser makes 'ranged requests' asking for subsequent parts of the media file so it can start playing as soon as some data is available, however, the CDN I'm using requires those requests to have this specific header, the problem is in chrome this header is added by chrome itself whereas in safari it's not, hence I wanted to intercept these requests which browser is making when I call load() on media element and add the header. I do not want to download the entire file before paying it, I know that works but that defeats the purpose.

Or Assayag
  • 5,662
  • 13
  • 57
  • 93
  • What did you try? What is the error message? – ceving Dec 11 '20 at 11:50
  • 1
    what did I try? I added src to audio tag, that's what I tried! I do not know how to set a custom header for audio tags that's what I asked, what is the error message? there is no error, the question is looking for a way to achieve something I have no idea about, I have read some answers where people say it's not possible –  Dec 11 '20 at 11:52
  • @ceving I think you're confused, I am not making any request by my own, the browser is doing it when I call load(), I wanna intercept that to modify it! –  Dec 11 '20 at 11:56
  • 1
    A question needs a [mcve]. And the for MCVE it is relevant, that it works. Otherwise it is not reproducible. – ceving Dec 11 '20 at 12:07
  • @cerving Alright, I'll keep than in mind, thanks for editing the question! –  Dec 11 '20 at 12:12
  • [check this out!](https://stackoverflow.com/questions/11214718/is-it-possible-to-alter-http-requests-header-using-javascript) – cl3m3c7 Dec 14 '20 at 13:54
  • From what I understand and read from https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio, as of date, it is not possible to set the custom headers. Do you have control on the server side? If so, maybe make changes there to make it compatible or check if safari can insert gzip header somehow – manishg Dec 15 '20 at 04:15
  • @manishg no I do not have any control server-side otherwise it would have been much easier, I guess the only way left for me is to download the entire video via js and pass it to media tags –  Dec 15 '20 at 14:49

1 Answers1

5

Since what you want to do is load then play, how about combinining your request with a XMLHttpRequest style pattern, using something like fetch?

Like:

HTML

<!-- just an indicator, in case the file is large -->
<div id="loading"><em>File is loading. Please wait...</em></div>

<!-- initially hide the audio tag. Also, change the 'src' to 'data-src' so it doesn't automatically load -->
<audio id="audio" style="display: none;" data-src="https://upload.wikimedia.org/wikipedia/commons/transcoded/7/7b/FurElise.ogg/FurElise.ogg.mp3" controls></audio>

Javascript

// define variables
  var audioEl = document.getElementById("audio");
  function fetchAudioFile() {
    // go get the file
    var requestObj = new Request(audioEl.dataset.src, {
        method: 'GET',
        headers: {
          'Accept-encoding': 'gzip'   // add your header(s)
        },
        referrerPolicy: 'no-referrer'
    });

    fetch(requestObj).then(function(response) {
      return response;
    }).then(async function(outcome) {
      const blob = await outcome.blob();
      // convert our blob to a url that can be used by the audio tag
      const url = window.URL.createObjectURL(blob);
      // replace the source
      audioEl.src = url;
      // hide the helpful text
      document.getElementById("loading").style["display"] = "none";
      // show the audio tag
      audioEl.style["display"] = "block";
      // play it immediately
      audioEl.play();
    });
  };

// get the file
  fetchAudioFile();

Hopefully this helps. Please note though that depending on the browser, sometimes the audio might not autoplay unless the user first interacts with the page or explicitly gives permission.

Deolu A
  • 752
  • 1
  • 6
  • 13
  • 1
    I do not want to download the entire file before playing. –  Dec 16 '20 at 15:01
  • when you add a source and load in let's say chrome, the browser makes 'ranged requests' asking for subsequent parts of the media file so it can start playing as soon as some data is available, however, the CDN I'm using requires those requests to have this specific header, the problem is in chrome this header is added by chrome itself where as in safari it's not, hence I wanted to intercept these requests which browser is making when I call load() on media element and add the header, hope you got a clearer picture now... –  Dec 16 '20 at 15:03
  • Okay - I see you've added this clarification to your original question. I don't think there's a way (at the moment) to 'intercept' these requests, IMO it's better to control the fetching yourself (and thus, be sure the behaviour is what you want regardless of browser). If you don't want to download the whole file before playing, you can still possibly adapt my answer above into a stream that can be loaded and played as it's being 'piped' in. Please see here for some ideas: https://developer.mozilla.org/en-US/docs/Web/API/Body/arrayBuffer – Deolu A Dec 16 '20 at 17:31