title: Live audio using ffmpeg, javascript and nodejs
body: <p>I am new to this thing. Please don't hang me for the poor grammar. I am trying to create a proof of concept application which I will later extend. It does the following: We have a html page which asks for permission to use the microphone. We capture the microphone input and send it via websocket to a node js app.</p>
  
  <p>JS (Client):</p>
  
  <pre><code>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){});
  </code></pre>
  
  <p>In the server we take each incoming buffer, run it through ffmpeg, and send what comes out of the std out to another device using the node js 'http' POST. The device has a speaker. We are basically trying to create a 1 way audio link from the browser to the device.</p>
  
  <p>Node JS (Server):</p>
  
  <pre><code>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) =&gt; {
    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) {});
  </code></pre>
  
  <p>The device supports only continuous POST and only a couple of formats (ulaw, aiff, wav) </p>
  
  <p>This solution doesn't seem to work. In the device speaker we only hear something like white noise.</p>
  
  <p>Also, I think I may have a problem with the buffer I am sending to the ffmpeg std in -> Tried to dump whatever comes out of the websocket to a .wav file then play it with VLC -> it plays everything in the record very fast -> 10 seconds of recording played in about 1 second.</p>
  
  <p>I am new to audio processing and have searched for about 3 days now for solutions on how to improve this and found nothing.</p>
  
  <p>I would ask from the community for 2 things:</p>
  
  <ol>
  <li><p>Is something wrong with my approach? What more can I do to make this work? I will post more details if required.</p></li>
  <li><p>If what I am doing is reinventing the wheel then I would like to know what other software / 3rd party service (like amazon or whatever) can accomplish the same thing.</p></li>
  </ol>
  
  <p>Thank you.</p>