使用ffmpeg,javascript和nodejs实时播放音频

时间:2017-11-08 14:51:16

标签: javascript node.js ffmpeg audio-streaming audio-recording

我是这个人的新手。请不要因为语法不好而挂我。我正在尝试创建一个概念验证应用程序,我稍后会扩展它。它执行以下操作:我们有一个html页面,要求允许使用麦克风。我们捕获麦克风输入并通过websocket将其发送到节点js app。

JS(客户):

var bufferSize = 4096;
var socket = new WebSocket(URL);
var myPCMProcessingNode = context.createScriptProcessor(bufferSize, 1, 1);
myPCMProcessingNode.onaudioprocess = function(e) {
  var input = e.inputBuffer.getChannelData(0);
  socket.send(convertFloat32ToInt16(input));
}

function convertFloat32ToInt16(buffer) {
  l = buffer.length;
  buf = new Int16Array(l);
  while (l--) {
    buf[l] = Math.min(1, buffer[l])*0x7FFF;
  }
  return buf.buffer;
}

navigator.mediaDevices.getUserMedia({audio:true, video:false})
                                .then(function(stream){
                                  var microphone = context.createMediaStreamSource(stream);
                                  microphone.connect(myPCMProcessingNode);
                                  myPCMProcessingNode.connect(context.destination);
                                })
                                .catch(function(e){});

在服务器中,我们获取每个传入缓冲区,通过ffmpeg运行它,并使用节点js'http'POST将std输出的内容发送到另一个设备。该设备有一个扬声器。我们基本上尝试创建从浏览器到设备的单向音频链接。

节点JS(服务器):

var WebSocketServer = require('websocket').server;
var http = require('http');
var children = require('child_process');

wsServer.on('request', function(request) {
  var connection = request.accept(null, request.origin);
  connection.on('message', function(message) {
    if (message.type === 'utf8') { /*NOP*/ }
    else if (message.type === 'binary') {
      ffm.stdin.write(message.binaryData);
    }
  });
  connection.on('close', function(reasonCode, description) {});
  connection.on('error', function(error) {});
});

var ffm = children.spawn(
    './ffmpeg.exe'
   ,'-stdin -f s16le -ar 48k -ac 2 -i pipe:0 -acodec pcm_u8 -ar 48000 -f aiff pipe:1'.split(' ')
);

ffm.on('exit',function(code,signal){});

ffm.stdout.on('data', (data) => {
  req.write(data);
});

var options = {
  host: 'xxx.xxx.xxx.xxx',
  port: xxxx,
  path: '/path/to/service/on/device',
  method: 'POST',
  headers: {
   'Content-Type': 'application/octet-stream',
   'Content-Length': 0,
   'Authorization' : 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
   'Transfer-Encoding' : 'chunked',
   'Connection': 'keep-alive'
  }
};

var req = http.request(options, function(res) {});

设备仅支持连续POST,只支持几种格式(ulaw,aiff,wav)

此解决方案似乎不起作用。在设备扬声器中,我们只能听到白噪声。

另外,我想我可能在发送到ffmpeg std的缓冲区有问题 - >试图将从websocket发出的任何东西转储到.wav文件然后用VLC播放 - >它可以非常快速地播放记录中的所有内容 - >录制10秒钟约1秒钟。

我是音频处理的新手,现在已经搜索了大约3天的时间来寻找有关如何改进这一点的解决方案,但却一无所获。

我会向社区提出两件事:

  1. 我的做法有问题吗?我还能做些什么来完成这项工作?如果需要,我会发布更多细节。

  2. 如果我正在做的是重新发明轮子,那么我想知道其他软件/第三方服务(如亚马逊或其他什么)可以完成同样的事情。

  3. 谢谢。

0 个答案:

没有答案