HTML JavaScript 中音频缓冲区的文件输入

HTML File Input to Audio Buffer in JavaScript

我正在努力编写一个简单的 HTML 页面,该页面的表单将音频文件作为输入并将其传递给 JavaScript 文件进行操作。

我有什么

index.html

<html lang="en">
  <head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  </head>
  <body>
    <main role="main" class="container">
      <form action="#" method="POST" enctype="multipart/form-data" class="audio-input-form">
          <label>Audio File:</label>
          <input accept="audio/*" type="file" name="audio_file"/>
          <input type="submit" value="Get BPM" />
      </form>
    </main>
     <script type="text/javascript" src="app.js"></script>
  </body>
</html>

app.js

// Package from NPM I import
import { analyze } from 'web-audio-beat-detector';

## here I want to be able to get and manipulate the audio data

想要的结果

提交表单时,我只想在 JavaScript 文件中提供实际文件数据(我猜是一个数组缓冲区)。我希望使用 this tutorial 将它变成 AudioBuffer 但我不清楚如何实际传递数据。

我尝试在我的 JS 文件中使表单操作成为一个函数并使用 onClick 函数,但似乎都不起作用。我需要某种形式的 XHR 吗?我对它们的目的感到困惑,我不想要任何类型的服务器 运行 为此,只需要一个 HTML 页面和一个在浏览器中运行的 JavaScript 文件。

我创建了一个甚至不使用表单的小示例。如果你只有一个输入,你可以监听它的 onchange 事件。这至少对本演示的目的有效。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <input id="audio-file" accept="audio/*" disabled type="file"/>
        <script>
            import('https://dev.jspm.io/web-audio-beat-detector')
                .then(({ default: { analyze }}) => {
                    const $audioFileInput = document.getElementById('audio-file');

                    $audioFileInput.disabled = false;
                    $audioFileInput.onchange = async () => {
                        const file = $audioFileInput.files[0];

                        if (file !== undefined) {
                            $audioFileInput.disabled = true;

                            const arrayBuffer = await file.arrayBuffer();
                            const audioContext = new AudioContext();
                            const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);

                            alert(await analyze(audioBuffer));

                            $audioFileInput.disabled = false;
                        }
                    };
                });
        </script>
    </body>
</html>

我还通过 jspm.io 加载了 web-audio-beat-detector,但在实际应用程序中,您可能希望将它与 webpack 之类的东西捆绑在一起。

像我在这里所做的那样,每次你想解码一些音频数据时都创建一个 AudioContext 是非常浪费的。如果您计划解码多个文件,重用一个 AudioContext 会更有意义。

另请注意,我仅在最新版本的 Firefox 和 Chrome 中对此进行了测试。不幸的是,它在 Safari 中不起作用。让它在 Safari 中工作需要更多的代码,这就是我省略它的原因。

文件有多大?理想情况下,您无需上传整个文件即可分析文件的第一部分。不确定节拍检测算法是如何工作的,但您可以创建一个读取缓冲区来获取要分析的文件的前 N ​​bytes/seconds。