title: Using Google Cloud Speech API from javascript & Web Audio
body: <p>I am trying to send a LINEAR16 PCM encoded audio to Google cloud speech API(using REST API). I am getting audio from microphone using Web Audio API and sending base64 encoded data to the server.  I am getting an empty {} every time.</p>
  
  <p>First I  stored audio buffers  from stream to a array</p>
  
  <pre><code>navigator.mediaDevices.getUserMedia({ 'audio': &lt;MediaTrackConstraints&gt;{
    echoCancellation: true,
    channelCount: 1,
    sampleRate: 16000,
    sampleSize: 16
  }, 'video': false})
  .then((stream: MediaStream) =&gt; {
    // to store audio chunks
    // Create AUdio Context ANd set Stream
    this.context = new AudioContext();
    this.sourceNode = this.context.createMediaStreamSource(stream);
    // Processing Node WIll give rAW data IN PCM32 bit format
    this.processor = this.context.createScriptProcessor(8192, 1, 1);
    this.sourceNode.connect(this.processor);
    this.processor.connect(this.context.destination);
    this.processor.onaudioprocess = (e: AudioProcessingEvent) =&gt; {
      // Raw Audio IN e.InputBuffer WHich Is A Audio Buffer
      this.buffer.push(e.inputBuffer);
    };
  }).catch( () =&gt; {
    this.dom.sendNotifications('Warning', 'Failed To Record Audio', 'warning');
  });
  </code></pre>
  
  <p>Then I stopped recording audio and appended all AudioBuffers in the array.</p>
  
  <pre><code>// Merge Array of Buffers Into single Buffer
  const mergedBuffer: AudioBuffer = this.appendBuffers(this.buffer);
  // Convert to Int16 Data &amp; base64
  const intArray: Int16Array =this.bufferToInt16PCM(mergedBuffer.getChannelData(0));
  const base64: string = this.intToBase64(intArray);
  this.sendRequestToGoogleAPI(base64);
  // Release Resources
  this.processor.disconnect();
  this.sourceNode.disconnect();
  this.context.close();
  this.buffer = [];
  </code></pre>
  
  <p>This is how I Appended the buffers (appendBuffer function)</p>
  
  <pre><code>let mergedBuffer: AudioBuffer = buffers[0];
  this.sampleRate = mergedBuffer.sampleRate;
  for (let i = 1; i &lt; buffers.length; i++) {
    const tempBuffer: AudioBuffer = this.context.createBuffer(mergedBuffer.numberOfChannels,
      buffers[i].length + mergedBuffer.length, mergedBuffer.sampleRate);
    const channel = tempBuffer.getChannelData(0);
    channel.set(mergedBuffer.getChannelData(0), 0);
    channel.set(buffers[i].getChannelData(0), mergedBuffer.length);
    mergedBuffer = tempBuffer;
  }
  return mergedBuffer;
  </code></pre>
  
  <p>This code is used to convert float32 to int16</p>
  
  <pre><code>let bufferLength = buffer.length - 1;
  const intArray = new Int16Array(bufferLength);
  while (bufferLength !== -1) {
    const temp = Math.max(-1, Math.min(1, buffer[bufferLength]));
    intArray[bufferLength] = temp &lt; 0 ? temp * 0x8000 : temp * 0x7FFF;
    bufferLength--;
  }
  return intArray;
  </code></pre>
  
  <p>And finally converted array buffer to base64 before sending</p>
  
  <pre><code>const binaryString: string = new Uint8Array(intArray)
            .reduce((data, byte) =&gt; data + String.fromCharCode(byte), '');
  const base64Sring: string = btoa(binaryString);
  return base64Sring;
  </code></pre>
  
  <p>I Used Angular HTTPclient for sending to speech api</p>
  
  <pre><code>const data = {
    'config': {
      'encoding': 'LINEAR16',
      'sampleRateHertz': this.sampleRate,
      'languageCode': 'en-US'
    },
    'audio': {
      'content': base64
    }
  };
  console.log(data);
  this.httpc.post('https://speech.googleapis.com/v1/speech:recognize?key=' +
  'myApiKey', data
  ).subscribe(
    (res) =&gt; {
      console.log(res);
    },
    (err) =&gt; {
      console.log(err);
    }
  );
  </code></pre>
  
  <p>This is my first time working with web audio and I think I went wrong  with conversion .</p>
  
  <p>Thanks</p>