Javascript 将实时音频流传输到Node.js服务器
我正在做一个项目,我需要向Node.js服务器发送一个音频流。我可以使用此功能捕获麦克风声音:Javascript 将实时音频流传输到Node.js服务器,javascript,node.js,audio,Javascript,Node.js,Audio,我正在做一个项目,我需要向Node.js服务器发送一个音频流。我可以使用此功能捕获麦克风声音: function micCapture(){ 'use strict'; navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; var constraints = { audio: true,
function micCapture(){
'use strict';
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
var constraints = {
audio: true,
video: false
};
var video = document.querySelector('video');
function successCallback(stream) {
window.stream = stream; // stream available to console
if (window.URL) {
video.src = window.webkitURL.createObjectURL(stream);
} else {
video.src = stream;
}
//Send audio stream
//server.send(stream);
}
function errorCallback(error) {
console.log('navigator.getUserMedia error: ', error);
}
navigator.getUserMedia(constraints, successCallback, errorCallback);
}
正如你所看到的,我能够捕获音频并在网站上播放
现在我想将该音频流发送到Node.js服务器,并将其发送回其他客户端。像语音聊天,但我不想使用WebRTC,因为我需要服务器中的流。我怎样才能做到这一点?我可以使用socket.io-stream执行此操作吗?在我看到的示例中,他们录制了音频并发送了一个文件,但我需要“实时”音频。我最近使用socket.io将实时音频从浏览器上传到服务器。我将在这里回答,以防其他人需要它
var stream;
var socket = io();
var bufferSize = 1024 * 16;
var audioContext = new AudioContext();
// createScriptProcessor is deprecated. Let me know if anyone find alternative
var processor = audioContext.createScriptProcessor(bufferSize, 1, 1);
processor.connect(audioContext.destination);
navigator.mediaDevices.getUserMedia({ video: false, audio: true }).then(handleMicStream).catch(err => {
console.log('error from getUserMedia', err);
});
当用户接受使用麦克风的权限时,handleMicStream
将运行
function handleMicStream(streamObj) {
// keep the context in a global variable
stream = streamObj;
input = audioContext.createMediaStreamSource(stream);
input.connect(processor);
processor.onaudioprocess = e => {
microphoneProcess(e); // receives data from microphone
};
}
function microphoneProcess(e) {
const left = e.inputBuffer.getChannelData(0); // get only one audio channel
const left16 = convertFloat32ToInt16(left); // skip if you don't need this
socket.emit('micBinaryStream', left16); // send to server via web socket
}
// Converts data to BINARY16
function convertFloat32ToInt16(buffer) {
let l = buffer.length;
const buf = new Int16Array(l / 3);
while (l--) {
if (l % 3 === 0) {
buf[l / 3] = buffer[l] * 0xFFFF;
}
}
return buf.buffer;
}
让你的socket.io服务器监听micBinaryStream
,你应该会得到数据。我需要google api的BINARY16
格式的数据如果不需要,可以跳过对convertFloat32ToInt16()的函数调用
重要的
当需要停止侦听时,必须断开处理器的连接并结束流。运行下面的函数closeAll()
function closeAll() {
const tracks = stream ? stream.getTracks() : null;
const track = tracks ? tracks[0] : null;
if (track) {
track.stop();
}
if (processor) {
if (input) {
try {
input.disconnect(processor);
} catch (error) {
console.warn('Attempt to disconnect input failed.');
}
}
processor.disconnect(audioContext.destination);
}
if (audioContext) {
audioContext.close().then(() => {
input = null;
processor = null;
audioContext = null;
});
}
}
我明白了,这是个老问题。我也在做同样的事情(除了我的服务器不运行node.js,并且是用C#编写的)并且偶然发现了这一点
我不知道是否还有人感兴趣,但我已经详细阐述了一些。不推荐使用的createScriptProcessor的当前替代方案是AudioWorklet接口
发件人:
1.32.1。概念
AudioWorklet对象允许开发人员提供脚本(如JavaScript或>WebAssembly代码)在渲染线程上处理音频,支持自定义>音频节点。此处理机制确保脚本>代码与音频图中的其他内置音频节点同步执行
据我所知,不能用Javascript实现接口,但可以扩展从Javascript派生的类
我们需要的是:
所以我确实写了一个处理器,它只是用输入值镜像输出并显示它们
class CustomAudioProcessor extends AudioWorkletProcessor {
process (inputs, outputs, parameters) {
const input = inputs[0];
const output = output[0];
for (let channel = 0; channel < input.length; ++channel) {
for (let i = 0; i < input[channel].length; ++i) {
// Just copying all the data from input to output
output[channel][i] = input[channel][i];
// The next one will make the app crash but yeah, the values are there
// console.log(output[channel][i]);
}
}
}
}
工作!祝你好运!:) 是的,您当然可以使用WebSocket将音频从客户端流到服务器。。。我建议您先编写一些代码,然后再回来回答一些具体的编程问题。。。正如您所说,上面的代码并不是特定于您的套接字问题的,谢谢您的建议。我将编写一些代码并更新问题。您在这方面有什么进展吗?我最终尝试了WebRTC,但最终放弃了该项目
function record() {
constraints = { audio: true };
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
audioCtx = new AudioContext();
var source = audioCtx.createMediaStreamSource(stream);
audioCtx.audioWorklet.addModule("custom-audio-processor.js").then(() => {
customAudioProcessor = new AudioWorkletNode(audioCtx, "custom-audio-processor");
source.connect(customAudioProcessor);
customAudioProcessor.connect(audioCtx.destination);
})
audioCtx.destination.play();