如何将Int16Array缓冲区保存到WAV文件节点JS

时间:2018-07-18 10:01:28

标签: node.js buffer wav fs audiocontext

在音频处理过程中,我正在将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文件?

1 个答案:

答案 0 :(得分:2)

在O / P问题上,试图将数据直接写入并添加到现有文件中,这是行不通的,因为WAVE文件需要有一个标头,而仅通过创建一个标头就不能有标头使用createWriteStream写入文件流。您可以在"WAVE PCM soundfile format"处查看该标头格式。

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

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

// 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来存储和标识属于相应客户端的每个流项目。