Jan Louda
Jan Louda

Reputation: 23

IBM Watson TextToSpeech - cannot read property .pipe of undefined

I have the following code, straight from the documentation:

var TextToSpeechV1 = require('watson-developer-cloud/text-to- 
speech/v1');
var fs = require('fs');

var textToSpeech = new TextToSpeechV1({
iam_apikey: '---myapikey---',
url: 'https://stream.watsonplatform.net/text-to-speech/api/'
});

var synthesizeParams = {
text: 'Hello world, you dummy ass',
accept: 'audio/wav',
voice: 'en-US_AllisonVoice'
};

// Pipe the synthesized text to a file. 
textToSpeech.synthesize(synthesizeParams).on('error', function(error) {
console.log(error);
}).pipe(fs.createWriteStream('hello_world.wav'));

when I run it it gives the following error:

pi@raspberrypi:~/Desktop/tjbotcz_lite $ sudo node ttstest.js
/home/pi/Desktop/tjbotcz_lite/ttstest.js:16
textToSpeech.synthesize(synthesizeParams).on('error', function(error) {
                                         ^

TypeError: Cannot read property 'on' of undefined
    at Object.<anonymous> (/home/pi/Desktop/tjbotcz_lite/ttstest.js:16:42)
    at Module._compile (internal/modules/cjs/loader.js:654:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:665:10)
    at Module.load (internal/modules/cjs/loader.js:566:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:506:12)
    at Function.Module._load (internal/modules/cjs/loader.js:498:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:695:10)
    at startup (internal/bootstrap/node.js:201:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:516:3)

Any clues why? I have the same issue with TJBot, so I tried a simple example from documentation and voila - the same error. When I use my old service (with username and password, not api key) it works fine. I have the new version of watson-cloud library (3.13.1).

Thanks for any hints. Regards, Jan.

Upvotes: 2

Views: 647

Answers (3)

Ivan Monteiro
Ivan Monteiro

Reputation: 169

I implemented this using promises so I can wait for the audio file to be completely saved and then do further processing. Also, as others stated, the documentation was wrong and the correct way is to use audio.result.pipe() instead of audio.pipe().

function synthesize_audio(text, mp3Path) {
    return new Promise((resolve, reject) => {
    console.log(`> Synthesizing audio from text: "${text}"`)

    const textToSpeech = new TextToSpeechV1({
      authenticator: new IamAuthenticator({
        apikey: apikey,
      }),
      url: apiUrl,
    });

    const synthesizeParams = {
      text: text,
      accept: 'audio/mp3',
      voice: 'pt-BR_IsabelaV3Voice',
    };

    textToSpeech.synthesize(synthesizeParams)
    .then(audio => {    
      audio.result
            .pipe(fs.createWriteStream(mp3Path))
            .on('finish', resolve)
            .on('error', reject);
    })
    .catch(err => {
      console.log('error:', err);
    });
  });
}

You can then await and do what you want:

 await synthesize_audio(text, outputPath)
  .then(() => {
    //then you can safely do what you want
  })
}

Upvotes: 1

Theo Oliveira
Theo Oliveira

Reputation: 385

I looked here for help but the docs there are definitely wrong. I was able to solve this by using audio.result.pipe(fs.createWriteStream('audio.wav')

Upvotes: 4

Vidyasagar Machupalli
Vidyasagar Machupalli

Reputation: 2865

The below code works for me and generating an audio.wav file using the Text-to-Speech API Key

var TextToSpeechV1 = require('watson-developer-cloud/text-to-speech/v1');
var fs = require('fs');

var textToSpeech = new TextToSpeechV1({
  iam_apikey: '<API_KEY>',
  url: 'https://stream.watsonplatform.net/text-to-speech/api'
});

var synthesizeParams = {
  text: 'Hello world',
  accept: 'audio/wav',
  voice: 'en-US_AllisonVoice'
};

textToSpeech
  .synthesize(synthesizeParams, function(err, audio) {
    if (err) {
      console.log(err);
      return;
    }
    textToSpeech.repairWavHeader(audio);
    fs.writeFileSync('audio.wav', audio);
    console.log('audio.wav written with a corrected wav header');
});

Updated the code snippet and this works

Upvotes: 0

Related Questions