IBM Watson Speech-to-Text sending microphone data closes connection

Viewed 1398

I'm working through the tutorial for IBM Watson Speech-to-Text, using WebSocket for real time transcription. I'm using Angular.

The first 25 lines of code are copied from the API reference. This code successfully connects and initiates a recognition request. Watson sends me a message { "state": "listening" }.

I wrote function onClose() that logs when the connection closes.

I made a button that runs the handler $scope.startSpeechRecognition. This uses getUserMedia() to stream audio from the microphone and websocket.send() to stream the data to Watson. This isn't working. Clicking this button closes the connection. I presume that I'm sending the wrong type of data and Watson is closing the connection?

I moved websocket.send(blob); from onOpen to my handler $scope.startSpeechRecognition. I changed websocket.send(blob); to websocket.send(mediaStream);. I might have this wrong: 'content-type': 'audio/l16;rate=22050'. How do I know what bit rate comes from the microphone?

Is there a tutorial for JavaScript? When I google "IBM Watson Speech-to-Text JavaScript tutorial" at the top is an 8000-line SDK. Is the SDK required or can I write a simple program to learn how the service works?

Here's my controller:

'use strict';
app.controller('WatsonController', ['$scope', 'watsonToken',  function($scope, watsonToken) {
  console.log("Watson controller.");

  var token = watsonToken;
  var wsURI = "wss://stream.watsonplatform.net/speech-to-text/api/v1/recognize"
    + "?watson-token=" + token + '&model=en-US_BroadbandModel';

  var websocket = new WebSocket(wsURI); // opens connection to Watson
  websocket.onopen = function(evt) { onOpen(evt) }; // executes when a connection opens
  websocket.onclose = function(evt) { onClose(evt) }; // executes when a connection closes
  websocket.onmessage = function(evt) { onMessage(evt) }; // logs messages from Watson to the console
  websocket.onerror = function(evt) { onError(evt) }; // logs errors to the console

  function onOpen(evt) {
    var message = {
      action: 'start',
      'content-type': 'audio/flac',
      'interim_results': true,
      'max-alternatives': 3,
      keywords: ['colorado', 'tornado', 'tornadoes'],
      'keywords_threshold': 0.5
    };
    websocket.send(JSON.stringify(message));

    // Prepare and send the audio file.
    // websocket.send(blob);

    // websocket.send(JSON.stringify({action: 'stop'}));
  }

  function onClose() {
    console.log("Connection closed.");
  };

  function onMessage(evt) {
    console.log(evt.data); // log the message to the console
  }

  $scope.startSpeechRecognition = () => {
    console.log("Starting speech recognition.");
    var constraints = { audio: true, video: false };
    navigator.mediaDevices.getUserMedia(constraints)
    .then(function(mediaStream) {
      console.log("Streaming audio.");
      websocket.send(mediaStream);
    })
    .catch(function(err) { console.log(err.name + ": " + err.message); }); // log errors
  };

  $scope.stopSpeechRecognition = () => { // handler for button
    console.log("Stopping speech recognition.");
    websocket.send(JSON.stringify({action: 'stop'}));
  };

  $scope.closeWatsonSpeechToText = () => { // handler for button
    console.log("Closing connection to Watson.");
    websocket.close(); // closes connection to Watson?
  };

}]);

And here's my template:

<div class="row">
  <div class="col-sm-2 col-md-2 col-lg-2">
    <p>Watson test.</p>
  </div>
</div>

<div class="row">
  <div class="col-sm-2 col-md-2 col-lg-2">
    <button type="button" class="btn btn-primary" ng-click="startSpeechRecognition()">Start</button>
  </div>

  <div class="col-sm-2 col-md-2 col-lg-2">
    <button type="button" class="btn btn-warning" ng-click="stopSpeechRecognition()">Stop</button>
  </div>

  <div class="col-sm-2 col-md-2 col-lg-2">
    <button type="button" class="btn btn-danger" ng-click="closeWatsonSpeechToText()">Close</button>
  </div>
</div>
1 Answers
Related