我正在构建一个Web应用程序,该应用程序接收来自用户的输入,将其传递给IBM Watson Text to Speech API,然后播放结果。应用程序中唯一的页面包含一个输入列表,旁边有一个"侦听"按钮。单击该按钮后,我将从数据库中获取相关文本,并将其添加到API的有效负载中。
我可以从api中获得结果,它写在.mp3文件上,但在播放音频时,我遇到了两种类型的问题:
- 第一次单击按钮时,会创建文件,但不会播放音频。如果我再次按下相同的按钮,它将播放音频
- 第二个问题是,当我选择不同的文本时,会出现以下错误:
下是负责调用IBMTTS 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
方法的promise,因此您可以将自己的代码封装到promise中,并且只尝试在promise的分辨率上播放音频。如果你想保持相同的流量,那么:
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实际上是一个缓冲区,但在实际尝试将其写入文件之前。
你应该坚持使用;
,要么使用它们,要么不使用!