如何使用 Node.js 在本地主机上播放 IBM Watson Text To Speech 音频

How to play IBM Watson Text To Speech audio on localhost using Node.js

我正在构建一个 Web 应用程序,它接收用户的输入,将其传递给 IBM Watson Text To Speech API,然后播放结果。该应用程序的唯一页面包含一个输入列表,旁边有一个 'Listen' 按钮。单击按钮时,我从数据库中获取相关文本并将其添加到 API.

的有效负载中

我能够从 api 中获得结果,该结果写在 .mp3 文件上,但在播放音频时,我遇到了两类问题:

  1. 第一次点击按钮,创建文件但不播放音频。如果我再次按下 same 按钮,它会播放音频;
  2. 第二个问题是当我选择不同的文本时,出现以下错误:
    internal/buffer.js:72
  throw new ERR_OUT_OF_RANGE(type || 'offset',
  ^

RangeError [ERR_OUT_OF_RANGE]: The value of "offset" is out of range. It must be >= 0 and <= 15922. Received -1282654053
    at boundsError (internal/buffer.js:72:9)
    at Buffer.readInt32LE (internal/buffer.js:376:5)
    at TextToSpeechV1._this.repairWavHeader (C:\Users\Pedro\Documents\udemy\projetoNode\node_modules\ibm-watson\text-to-speech\v1.js:82:45)
    at IncomingMessage.<anonymous> (C:\Users\Pedro\Documents\udemy\projetoNode\node_modules\ibm-watson\text-to-speech\v1.js:45:35)
    at IncomingMessage.emit (events.js:228:7)
    at endReadableNT (_stream_readable.js:1185:12)
    at processTicksAndRejections (internal/process/task_queues.js:81:21) {
  code: 'ERR_OUT_OF_RANGE'

下面是负责调用 IBM TTS API 和播放音频的部分代码:

            // result from the mysql's query
            let comment = results[0].comentario;
            console.log("Comment: " + comment);

            //text_to_speech api
            let payload = {
                text: comment,
                accept: 'audio/mp3',
                voice: 'pt-BR_IsabelaV3Voice'
            }

            textToSpeech.synthesize(payload)
                .then(response => {
                    return textToSpeech.repairWavHeaderStream(response.result);
                })
                    .then(buffer => {
                        fs.writeFileSync('audio.mp3', buffer);
                        console.log('audio ok');
                    })
                .catch(err => {
                    console.log('error:', err);
                });

            const filePath = path.join(__dirname, 'audio.mp3')
            sound.play(filePath);

我正在使用 Express 和 Sound-Play 播放音频文件。

您违反了 Node.js 异步行为。这意味着您尝试在收到音频之前播放它。事实上,即使抛出错误,您也会尝试播放音频。在随后的播放中,您将播放之前下载的音频文件。 您的缓冲区错误很可能与同一问题有关。

您正在响应 synthesize 方法的承诺,因此您可以将自己的代码包装到承诺中,并且仅尝试在承诺解决时播放音频。如果您想保持与现在相同的流量:


  textToSpeech.synthesize(payload)
    .then(response => {
      return textToSpeech.repairWavHeaderStream(response.result);
    })
    .then(buffer => {
      fs.writeFileSync('audio.mp3', buffer);
      console.log('audio ok');
      return Promise.resolve();
    })
    .then(() => {
      const filePath = path.join(__dirname, 'audio.mp3');
      sound.play(filePath);
    })
    .catch(err => {
      console.log('error:', err);
             
    });

经过评论中的讨论,很明显您的缓冲区错误是因为您试图在 .mp3 文件上调用 repairWavHeaderStream。你不需要这一步,你的代码流程应该是:


  textToSpeech.synthesize(payload)
    .then(response => {
      fs.writeFileSync('audio.mp3', response.result);
      console.log('audio ok');
      return Promise.resolve();
    })
    .then(() => {
      const filePath = path.join(__dirname, 'audio.mp3');
      sound.play(filePath);
    })
    .catch(err => {
      console.log('error:', err);
             
    });

尽管理想情况下,您应该添加一个步骤来检查 response.result 实际上是一个缓冲区,然后再实际尝试将其写入文件。

您应该与您对 ; 的使用保持一致,要么使用它们,要么不使用它们!