Search code examples
javascripthtml5-audio

Webpage with 200 preloaded small audio files


I made a webpage for Thai alphabet learning and I want to voice over letters and sounds. Clicking on these tiles plays a really short mp3 file and there is about 200 things to click and listen which is 1mb in total.

enter image description here

I have difficulties:

  1. Preload all the mp3 files in the background.
  2. Download 1 file instead of 200.
  3. Delays in desktop safari when running audio, even for already played and cached files.
  4. Extreme delays in mobile browsers. Sometimes audio don't even play.

To play audio I tried something like this:

const audio = new Audio('path/to/audio.mp3');
audio.play();
...

And to let browser cache files I tried to address each one like so:

playlist.forEach(function(item) {
    fetch('path/to/audio.mp3');
    ...
});    

But this is just a draft. What will be the best approach to code it? Where do I look to improve it? Can I create an mp3 sprite? Or could it be <audio> tag with inlined base64 with preload attribute? Or maybe I could try <link rel="preload"> for some kind of mp3 sprite? Can I rely on browser's cache or I should try JavaScript library to control all the media manually? Will it works without delay if I store these files in local storage?


Solution

  • My current solution is to create some sort of a sprite as a JS collection where data is encoded as base64 strings:

    const playlist = new Map([
        ['consonant-bo-baimai', 'SUQzAw...AAAAAAKl'],
        ['consonant-cho-chang', 'AMVRJV...DIAAAAUA'],
        ['consonant-cho-ching', 'AUAAAA...Y29uYW50'],
    ]);
    

    Store it in the separated file away from main page and link it at the end of the page. Then I play audio using a single audio container, like so:

    let voiceover = new Audio();
    
    $('[data-audio]').on('click', function (event) {
        voiceover.src = 'data:audio/mpeg;base64,' + playlist.get($(this).data('audio'));
        voiceover.play();
    });
    

    In this case performance and downloading data seem okey.

    What didn't work:

    1. Set of <audio> tags on the pages with encoded base64 files into them. Desktop Safari and mobile browsers were freezing processing 200 of them.
    2. Set of <audio> tags with direct path to mp3 files and preload attribute. Desktop Safari wasn't really preloading files. There was an http code saying "partially loaded". And mobile browsers were freezing again.
    3. Preloading with .fetch() done in JavaScript hoping browsers will cache it. Running 200 fetches was freezing page in Safari again.