LePhenix47 / Audio-Visualizer_Younes-Lahouiti

This is a JavaScript audio visualizer that uses HTML5 `<canvas>` elements to create stunning visual representations of audio waveforms
https://lephenix47.github.io/Audio-Visualizer_Younes-Lahouiti/
1 stars 0 forks source link

[CONCEPT] How to play an uploaded audio file? #3

Open LePhenix47 opened 1 year ago

LePhenix47 commented 1 year ago

Here's how

1. Recovering the file

First we must get the file that uploaded by the user in an asynchronous function, here's how with both an input and a dropzone:

const inputFile = document.querySelector("input[type=file]");

inputFile.addEventListener("change", async (e) => {
  try {
    //We get the first and only file, also we need to wait for the transfer
    const fileUploaded = await e.target.files[0];
  } catch (error) {
    console.error(error);
  }
});

const dropzone = document.querySelector(".dropzone");

dropzone.addEventListener("drop", async (e) => {
  try {
    //Same here
    const fileUploaded = await e.dataTransfer.files[0];
  } catch (error) {
    console.error(error);
  }
});

2. Checking its type

We'll need to perform a type check if needed to check if the audio uploaded is indeed an audio file:

//...

//We get the type, for instance: audio/mpeg
const { type } = fileUploaded;
//We verify if it's an audio file by checking the type wihtout the extension
const fileType = type.split("/")[0];

const isNotAnAudioFile = fileType !== "audio";
if (isNotAnAudioFile) {
  //Add code displaying an error to the input or dropzone
  return;
}

3. Converting it to a base₆₄ string

Browsers cannot read binary data for security reasons, they only read text, so they must be converted into a base 64 string thus for that we'll create a function that returns a promise where a file reader will read it as text:

function transformAudioFileToBase64Text(audioFile) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    //Allows the conversion of binary data, in this case audio files, into a text format
    reader.readAsDataURL(audioFile);

    // When the audio file is loaded, extract the base64 string and resolve the promise with it
    reader.addEventListener("load", (e) => {
      const base64MediaString = reader.result;

      const isNotString = typeof base64MediaString !== "string";
      if (isNotString) {
        reject("Error: Base64 string not found.");
        return;
      }

      resolve(base64MediaString);
    });

    // If there's an error while reading the audio file, reject the promise with an error message
    reader.addEventListener("error", () => {
      reject("Error: Failed to read audio file.");
    });
  });
}

//...
input.addEventListener("change", async (e)=>{
//...
 const base64AudioString= await transformAudioFileToBase64Text(fileUploaded);
})

4. Creating or adding the audio string

We've converted our binary file into a base₆₄ string, now all we need is to create the audio element :

//...
 const base64AudioString= await transformAudioFileToBase64Text(fileUploaded);
const audioHTMLElement = new Audio(base64AudioString);
document.body.appendChild(audioHTMLElement);

Or change it's src attribute to the string if there was already an <audio> element:


//...
const audioHTMLElement = docuemnt.querySelector("audio");
input.addEventListener("change", async (e)=>{
//...
 const base64Audio = await transformAudioFileToBase64Text(fileUploaded);
audioHTMLElement.src = base64AudioString
})

5. (Optional) Authorize the audio context

If we need the audio context to create visual effects with a <canvas> element

If you create an AudioContext before the document receives any user interaction, it will be created in a "suspended" state, which means you'll need to call the resume() method after the user interacts with the page in order to activate it. Source: https://developer.chrome.com/blog/autoplay/#web-audio

So we'll need to create a function that will resume the audio context when the user makes a gesture, such as a button click:

// One-liner to resume playback when user interacted with the page.
const authButton = document.querySelector("button");
authButton.addEventListener("click", async () => {
  try {
    await audioContext.resume();
    console.log("Playback resumed successfully");
  } catch (error) {
    console.error(error);
  }
});
LePhenix47 commented 1 year ago

6) Base₆₄ string vs Blobs

There is another way to convert a file into readable data with the URL.createObjectUrl([File object]), the only difference being that unlike the base₆₄ string, the URL generated is a temporary Binary large object URL and will be invalid once the user closes the tab

In other words, the lifespan of a blob URL is tied to the document or web page that created it.