如何将 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 文件发送到客户端浏览器? [关闭]