1

I'm using ReactJS to develop a web page (.html + .js) that will be bundled in a USB drive and shipped to customers. This USB drive contains some audio (.wav) files that are played through an HTML5 audio element in the web page. Customers will open the HTML file through their browser and listen to the songs available inside the USB drive.

I used the recent Web Audio API (specifically the analyser node) to analyze the frequency data of the current playing audio and then draw a sort of visual audio spectrum on an HTML5 canvas element.

Sadly, I was using a NodeJS local webserver during the development. Now, I prepared everything for production, just to discover that due to CORS-related restrictions my JS code can't access the audio file through the Web Audio API. (This is because the URL protocol would be "file://", and there is no CORS policy defined for this protocol – This is the behaviour on Chrome and Firefox, using Safari it just works.)

The visual audio spectrum is an essential part of the design of this web page, and I'd hate to throw it away just because of the CORS policy. My idea is to embed inside the JS code a JSON representation of the frequency data for the audio file, and then to use the JSON object in sync with the playing audio file to draw a fake (not in real-time) spectrum.

I tried – modifying the original code I was using to draw the spectrum – to use the JS requestAnimationFrame loop to get the frequency data for each frame and save it to a JSON file, but the JSON data seems to be incomplete and some frames (a lot) are missing.

    this.audioContext = new AudioContext();

    // this.props.audio is a reference to the HTML5 audio element
    let src = this.audioContext.createMediaElementSource(this.props.audio);

    this.analyser = this.audioContext.createAnalyser();
    src.connect(this.analyser);

    this.analyser.connect(this.audioContext.destination);

    this.analyser.smoothingTimeConstant = 0.95;
    this.analyser.fftSize = 64;
    this.bufferLength = this.analyser.frequencyBinCount;
    this.frequencyData = new Uint8Array(this.bufferLength);


    [...]

    const drawSpectrum = () => {
      if (this.analyser) {
        this.analyser.getByteFrequencyData(this.frequencyData);
        /*
         * storing this.frequencyData in a JSON file here,
         * this works but I get sometimes 26 frames per seconds,
         * sometimes 2 frames per seconds, never 60.
         */
      }
      requestAnimationFrame(drawSpectrum);
    };
    drawSpectrum();

Do you have a better idea to fake the visual audio spectrum? How would you go to "circumvent" the CORS-related restrictions in this case? What could be a solid method to export audio frequency data to JSON (and then access it)?

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Andrea Corsini
  • 197
  • 1
  • 9
  • Can you put a simple web server onto the USB stick? Or maybe wrap the whole thing application up in Cordova Electron (which would have other advantages, such as having a known browser version)? – Thomas Jun 16 '20 at 12:33
  • @Thomas You're right I could. One way of solving the problem was to bundle it as an App using Electron. But I need it to be platform agnostic, while with Electron or any other package builder I would need different packages for different platforms/architectures. – Andrea Corsini Jun 16 '20 at 12:40
  • [This question](https://stackoverflow.com/questions/21756237/get-a-spectrum-of-frequencies-from-wav-riff-using-linux-command-line) might have some useful info on how to compute the spectrogram (= spectrum over time) offline. – Thomas Jun 16 '20 at 13:02

1 Answers1

1

This is one of the only cases where a data:// URL will come handy.
You can bundle your media file directly in your js or html file, as a base64 string and load it from there:

// a simple camera shutter sound
const audio_data = 'data:audio/mpeg;base64,SUQzAwAAAAAfdlRJVDIAAAABAAAAVFBFMQAAABsAAABTb3VuZEpheS5jb20gU291bmQgRWZmZWN0c1RBTEIAAAABAAAAVFlFUgAAAAEAAABUQ09OAAAAAQAAAFRSQ0sAAAABAAAAQ09NTQAAAB8AAABlbmcAb25saW5lLWF1ZGlvLWNvbnZlcnRlci5jb20AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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';

const button = document.getElementById( 'btn' );
const audio_ctx = new AudioContext();
// if you wish to use a MediaElementSource node:
function initMediaElementNode() {
  const audio_el = new Audio();
  audio_el.src = audio_data;
  document.body.append( audio_el );
  audio_el.controls = true;
  const node = audio_ctx.createMediaElementSource( audio_el );
  node.connect( audio_ctx.destination );
  // to prove the data passes through the AudioContext
  const analyser = audio_ctx.createAnalyser();
  analyser.fftSize = 32;
  node.connect( analyser );
  const arr = new Uint8Array( 32 );
  audio_el.onplay = (evt) => {
   setTimeout( ()=> {
    analyser.getByteFrequencyData( arr );
    console.log( 'analyser data', [...arr] );
   }, 150 );
  };
}
// if you wish to use an AudioBuffer:
async function initAudioBuffer() {
  const data_buf = dataURLToArrayBuffer( audio_data );
  const audio_buf = await audio_ctx.decodeAudioData( data_buf );
  button.onclick = (evt) => {
    const source = audio_ctx.createBufferSource();
    source.buffer = audio_buf;
    source.connect( audio_ctx.destination );
    source.start( 0 );
  };
  button.textContent = "play audio buffer";
}

button.onclick = (evt) => {
  initMediaElementNode();
  initAudioBuffer();
};

function dataURLToArrayBuffer( data_url ) {
  const byte_string = atob( data_url.split( ',' )[ 1 ] );
  return Uint8Array.from(
    { length: byte_string.length },
    (_, i) => byte_string.charCodeAt(i)
  ).buffer;
}
button { vertical-align: top; }
<button id="btn">click to start</button>
Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • I thought about the base64 data URI solution, but my audio files are between 50MB and 100MB in size, so I can't do this. Especially because of the data URI size limit forced by browsers. – Andrea Corsini Jun 17 '20 at 14:38
  • What dataURI limit? The only dataURI limitations that ever existed were regarding the length of the address in the address bar. You are not in this odd case. The one kimit you'll face is the max length of a string (512MB in v8), but if it is a problem, just split your string. – Kaiido Jun 17 '20 at 14:42
  • you are right, there are no data URI limitations as I wrongly thought. However, I tried this approach and I ended up with a too heavy JS file that slowed down the entire web browser - especially if you consider that the base64 data string is 33% bigger than the original file. My initial thought was about a JS variable of 2/3 MB for a 100MB file, storing just the retrieved frequency data as per my question. – Andrea Corsini Jun 18 '20 at 10:18
  • There is no real reasons that after parsing the js files "slows down" the page... There must be something wrong. Your visualization data will end up being similar or bigger than raw PCM data, and raw PCM data takes way more space than any compressed media data, far beyond 30% ;-) To do it correctly, store the byte data as b64 strings, in an IIFE, be sure to not keep any reference to that string. Parse like I do with my ArrayBuffer example. If you need a MediaElement, generate a Blob then a blob:// URI from it. – Kaiido Jun 18 '20 at 12:13