3

I'm having trouble loading an audio file then putting it into readAsArrayBuffer. I don't want the user to choose a file, I just want it to load one locally like so:

let file = new File('../music/song.mp3');
let reader = new FileReader();

reader.onload = function(e) {
    playSound(e.target.result);
}
reader.readAsArrayBuffer(file);

When I do the above, I get the following error:

Uncaught TypeError: Failed to construct 'File': 2 arguments required, but only 1 present.

So I try this:

let file = new File([''], '../music/song.mp3');

Which then produces this error:

Uncaught (in promise) DOMException: Unable to decode audio data

The size of what it loads is 0, which I believe is why it's producing this error.

Everything works fine when I let the user choose a file to load:

document.getElementById('open-file').onchange = function(evt) {
    let file = evt.target.files[0];

Does anyone know how to fix this?

  • 1
    You can't read a local filesystem file without user interaction, it would be a security risk otherwise. Also see [documentation for File()](https://developer.mozilla.org/en-US/docs/Web/API/File/File), it shows what arguments it takes – Patrick Evans Oct 25 '17 at 21:45
  • 1
    You will need to fetch this file, File constructor doesn't handle it and doesn't accept URIs as input. So what you seem to want is `fetch('../music/song.mp3').then(r=>r.arrayBuffer()).then(buf=>audioContext.decodeAudioData(buf).then(enjoyTheAudioBuffer);` – Kaiido Oct 26 '17 at 07:58

2 Answers2

0

As Patrick Evans stated, it's not at all possible because of security risks. Such a shame as you can easily play audio with HTML5, but you can't load the audio files and read them as an array buffer.

0

This loads a file using fetch and uses the Audio Web API to play it right away. You could, of course, make it play whenever by putting it in a function and calling it.

Is there something that prevents this or makes it undesirable?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Minimal Audio Example</title>
</head>
<body>
    <h1>Audio should play right away</h1>
    <p>You will need to add the audio example, though.</p>
</body>
<script type="module">
    const audioFileResponse = await fetch('./example-audio.mp3')
    const arrayBuffer = await audioFileResponse.arrayBuffer()
    const audioContext = new AudioContext();
    const audioBuffer = await audioContext.decodeAudioData(arrayBuffer)
    const source = audioContext.createBufferSource();
    source.buffer = audioBuffer;
    source.connect(audioContext.destination);
    source.start();
</script>
</html>
AlexJeffcott
  • 116
  • 2
  • 5