如何将 Int16Array 缓冲区保存到 wav 文件节点 js

Posted

技术标签:

【中文标题】如何将 Int16Array 缓冲区保存到 wav 文件节点 js【英文标题】:How to save Int16Array buffer to wav file node js 【发布时间】:2018-12-26 04:52:05 【问题描述】:

我在音频处理时将 ​​Int16Array 缓冲区发送到服务器

var handleSuccess = function (stream) 
        globalStream = stream;
        input = context.createMediaStreamSource(stream);
        input.connect(processor);

        processor.onaudioprocess = function (e) 
            var left = e.inputBuffer.getChannelData(0);
    var left16 = convertFloat32ToInt16(left);
    socket.emit('binaryData', left16);
        ;
    ;

    navigator.mediaDevices.getUserMedia(constraints)
        .then(handleSuccess);

在服务器中我尝试按如下方式保存文件

client.on('start-audio', function (data) 
        stream = fs.createWriteStream('tesfile.wav');
    );

    client.on('end-audio', function (data) 
         if (stream) 
            stream.end();
         
         stream = null;
    );

    client.on('binaryData', function (data) 
        if (stream !== null) 
            stream.write(data);
        
    );

但这不起作用所以我如何将此数组缓冲区保存为 wav 文件?

【问题讨论】:

我也需要这样做...您现在有解决方案了吗? 我试过使用这个github.com/Jam3/audiobuffer-to-wav,但没有任何运气。 @Ravimalya 在存储库中是否有一个可复制的示例?这使用socket.io吗? 是的@ChristosLytras,这是一个 git github.com/ravimallya/angular-node-google-voice-api。 /bin 目录中的 nodejs 服务器代码(socket.io)和录音机位于 src/app/dashboard 组件中。我正在发送 left16 数组缓冲区。实时转录工作正常。但是,我需要将录制的音频保存为服务器中的 wav 文件。 @Ravimalya 请检查我的答案和存储库,其中包含一个简单的项目,该项目演示了在服务器端使用 wav NPM 包。 【参考方案1】:

在 O/P 问题中,有人尝试将数据直接写入和添加到现有文件中,但由于 WAVE 文件需要有标头,而仅通过创建使用createWriteStream 写入文件流。您可以在"WAVE PCM soundfile format" 处查看该标题格式。

wav NPM 包,它可以帮助处理将数据写入服务器的整个过程。它有一个FileWriter 类,它创建了一个可以正确处理 WAVE 音频数据的流,并且它会在流结束时写入标题。

1。在 start-audio 事件上创建 WAVE FileWriter 流:

// Import wav package FileWriter
const WavFileWriter = require('wav').FileWriter;

...

// Global FileWriter stream.
// It won't handle multiple client connections; it's just for demonstration
let outputFileStream;

// The UUID of the filename that's being recorded
let id;

client.on('start-audio', function() 
  id = uuidv4();

  console.log(`start-audio:$id`);

  // Create a FileWriter stream using UUID generated for filename
  outputFileStream = new WavFileWriter(`./audio/recs/$id.wav`, 
    sampleRate: 16000,
    bitDepth: 16,
    channels: 1
  );
);

2。使用我们创建的流在binaryData事件上写入音频数据:

client.on('binaryData', function(data) 
  console.log(`binaryData:$id, got $data ? data.length : 0 bytes`);

  // Write the data directly to the WAVE file stream
  if (outputFileStream) 
    outputFileStream.write(data);
  
);

3。当我们收到end-audio 事件时结束流:

client.on('end-audio', function() 
  console.log(`end-audio:$id`);

  // If there is a stream, end it.
  // This will properly handle writing WAVE file header
  if (outputFileStream) 
    outputFileStream.end();
  

  outputFileStream = null;
);

我已使用此示例创建了一个 Github 存储库,您可以在此处找到:https://github.com/clytras/node-wav-stream。

请记住,处理这样的数据会导致问题,因为使用此代码,每个连接的客户端只有一个 FileWriter 流变量。您应该为每个客户端流创建一个数组,并使用客户端会话 ID 来存储和标识属于相应客户端的每个流项。

【讨论】:

非常感谢。结束文件流需要做一个小改动。我们必须检查if (!outputFileStream.closed) ,而不是if (outputFileStream) 我认为您不必这样做,因为如果我们有一个流outputFileStream !== null,那么它不会关闭,因为我们在end-audio 事件上设置了outputFileStream = null。在检查它是否关闭之前检查它是否存在更安全,因为如果没有对象,那么使用closed 进行检查将导致错误。所以最好做if (outputFileStream && !outputFileStream.closed) 是的,我同意。 我试过你的解决方案,但它没有转换正确的 wav 文件,里面没有音频 @Vimal github.com/ravimallya/angular-node-google-voice-api 你可以在这里试试。我没有更新代码,但这个答案肯定会对你有所帮助。如果您遇到任何问题,请告诉我们。

以上是关于如何将 Int16Array 缓冲区保存到 wav 文件节点 js的主要内容,如果未能解决你的问题,请参考以下文章

加载和保存 WAV 文件

如何将服务器生成的音频 wav 文件发送到客户端浏览器? [关闭]

您如何分析 PCM 或 WAV 样本的基频? [关闭]

如何将您在 python 中创建的 .wav 文件保存到指定目录?

在 C++ 中将缓冲区导出到 WAV

通过 C 中的 FFT 将 1000Hz 噪声添加到 wav 文件