I'm learning to use the Watson Speech JS SDK. In particular I like Transcribe from Microphone, with Alternatives. I'm generating my token with a Firebase Cloud Function. I'm using AngularJS, not JQuery. The first problem I'm running into is
var stream = WatsonSpeech.SpeechToText.recognizeMicrophone(Object.assign(token, {
objectMode: true,
format: false,
wordConfidence: true
}));
I got this error message:
WatsonSpeechToText: missing required parameter: opts.token
(Using $scope.token
or token
makes no difference.)
Looking up this error in the documentation:
module.exports = function recognizeMicrophone(options) {
if (!options || !options.token) {
throw new Error('WatsonSpeechToText: missing required parameter: opts.token');
}
OK, it's looking for an options
object. I fixed the error with this code:
const options = {
token: $scope.token,
objectMode: true,
format: false,
wordConfidence: true
};
console.log(options);
var stream = WatsonSpeech.SpeechToText.recognizeMicrophone(options);
Now I get this error:
WebSocket connection to 'wss://stream.watsonplatform.net/speech-to-text/api/v1/recognize?model=en-US_BroadbandModel&watson-token=[object%20Object]' failed: HTTP Authentication failed; no valid credentials available
The options
object logs this:
token:
access_token: "eyJraWQiOiIyMDIwMDIyNTE4MjgiLCJhbGciOiJSUzI1NiJ9.eyJpYW1faWQiOiJp0tU2..."
expiration: 1585332575
expires_in: 3600
refresh_token: "OKC8z8ebLMzZcrAt6YgInnJJn0UIx1P3NTeDvdEC3kJqIQ7Yn9J9iu6-DF..."
scope: "ibm openid"
token_type: "Bearer"
objectMode: true
format: false
wordConfidence: true
smart_formatting: false
The token is a JSON object, which includes the access_token
. Is this what the SDK wants? The RecognizeStream documentation doesn't say whether it wants the JSON token or just the naked access_token
.
Adding 000
to the expiration
field shows that I have 53 minutes left on this token.
I'm using the API key that's specific to my Speech-to-Text service.
Any other suggestions?
Version 0.37.0 of the SDK introduced breaking changes:
This is related to IBM's move from Cloud Foundry services with username/password auth to Services with IAM auth and api keys. The SDK documentation says:
The
options
object looks like this if you use an api key:If you leave out the token property you get this error message:
What that means is, if you're getting your token from Cloud Foundry (CF) the property must be
opts.token
(oroptions.token
); but if you're getting your token from IAM auth and an api-key, which is calledRC
for no reason I know of, then the property must beopts.accessToken
(oroptions.accessToken
).Confusing the matter, the demo source code implies that
access_token
is the property name:Object.assign
is taking thetarget
token object as it comes from IBM and then adding or replacing the properties and values in thesource
object. Because the property isaccess_token
in the IAM token you'd think that, because the demo runs,access_token
is the property. But apparently the demo is running on a Cloud Foundry token, which can use eithertoken
oraccess_token
as the property name.If you get this error message:
then you're using neither
token
noraccessToken
as the property name.If you get this error message:
then you're using
token
with a token generated with an IAM api-key. Or your token is expired. You can check that easily by putting this code in your app to tell you how many minutes are left on your token:You can test if your token is valid from the CLI. First get a new token:
then request the language models:
I had another problem in my code. I was updating the IBM Speech-to-Text SDK but my code was linking to an old SDK I'd installed with bower three years ago. I didn't realize that I was using 0.33.1 when 0.38.0 is the latest version. Add this to your code to catch this problem:
With the old SDK I was getting an old error message that didn't even mention the new property name:
My blog post has more about IBM Cloud Speech-to-Text.