如何在 javascript 中使用 audioWorklet 和 AudioWorkletProcessor 录制音频?

Posted

技术标签:

【中文标题】如何在 javascript 中使用 audioWorklet 和 AudioWorkletProcessor 录制音频?【英文标题】:How to record audio using audioWorklet and AudioWorkletProcessor in javascript? 【发布时间】:2019-06-14 06:25:52 【问题描述】:

我有以下逻辑记录(在 AudioContext 中设置采样率 = 16000,仅考虑一个通道进行单声道记录)

    我从 AudioWorklet 设置了一个参数 shouldRecord,根据该参数,AudioWorkletProcessor 将开始将数据放入缓冲区,如下所示
  process(inputs, outputs, parameters) 
    const isRecordingValues = parameters.isRecording;
    //taking first input
    var input0 = inputs[0];
    var inputChannel = input0[0];
    if (isRecordingValues.length ===1)
      const shouldRecord = isRecordingValues[0] === 1;
      if (!shouldRecord && !this._isBufferEmpty()) 

        this._flush();
        this._recordingStopped();
      

      if (shouldRecord) 
            this._appendToBuffer(inputChannel);
      

    
    return true;
  



_appendToBuffer 如下:

  _appendToBuffer(value) 
    if (this._isBufferFull()) 
      this._flush();
    

    // Here _buffer is of type Float32Array 
    this._buffer.set(value, this._bytesWritten);
    this._bytesWritten += value.length;
  

    在 _flush 方法中,我将 _buffer 的内容发送到 AudioWorklet,如下所示:
    var blob = this._exportWAV(buffer, this._bytesWritten);
    this.port.postMessage(
      eventType: 'data',
      audioBuffer: blob 
    );

这里的缓冲区包含 -1.0 到 1.0 之间的值。

    我将 AudioWorklet 中的数据作为 ArrayBuffer 对象接收,并将其下载为 Wave 文件。无论文件大小如何,我都可以在 Windows Media Player 中打开文件而不会出错,但持续时间不到一秒,播放结束。

我认为我在 process 方法中做错了,缓冲区中记录的数据格式不正确。

我在这里做错了什么?

【问题讨论】:

缺少太多细节,无法确切知道发生了什么。作为测试,使用缓冲区而不是 blob 发布消息。然后你可以更好地看到正在发生的事情,然后可能会将缓冲区转换为 wav 文件。 如果你把代码放在github上,我们会更容易调查... 我尝试了@RaymondToy 的建议。这样做时,我意识到我将数据从 audioWorklet 发送到烧瓶应用程序的方式是错误的。我应该将 float32Array 或 blob 发送到 Flask 应用程序。在 Flask 应用程序中收到后,我必须将其转换为 16 位浮动数据,这样我才能听到声音。我会在回答中展示我是如何做到的。 很高兴帮助您弄清楚发生了什么! 【参考方案1】:

我将_flush方法改成如下:

_flush() 

  let buffer = this._buffer;
  if (this._bytesWritten < this._bufferSize) 
    buffer = buffer.slice(0, this._bytesWritten);
  
  this.port.postMessage(
    eventType: 'data',
    audioBuffer: buffer
  );

  this._initBuffer();

所以我直接将我的缓冲区发送到 AudioWorklet。当我在 AudioWorklet 中收到此缓冲区时,我将其作为 Blob 发送到 Flask 应用程序,如下所示

const audioData = e.data.audioBuffer.buffer;
socket.emit( 'my event', 
   blob : new Blob([audioData],  type: 'audio/wav' )
);

这让我可以在 Flask 应用程序中使用 -1.0 到 1.0 之间的简单浮点数。然后我用下面的函数转换这些浮点数

def convert(raw_floats):
   data = raw_floats
   floats = array.array('f', data)
   samples = [int(sample * 32767)
           for sample in floats]
   raw_ints = struct.pack("<%dh" % len(samples), *samples)
   return raw_ints

我将这些 raw_ints 保存到 WAVE 文件中,该文件可在 Windows Media Player 中播放。

【讨论】:

以上是关于如何在 javascript 中使用 audioWorklet 和 AudioWorkletProcessor 录制音频?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JavaScript 中使用 DCMTK 库

如何在 Javascript 中使用路由

如何在 jQuery 选择器中使用 JavaScript 变量?

在 Rails 中如何在使用 javascript_include_tag 之前检查 javascript 文件是不是存在

如何在 JavaScript 文件中使用 Django 变量?

如何在 iOS 的目标 C 中使用 javascript 代码?