解决方法 1
正如我在评论中提到的,节点中有一个google-tts-concat-ssml 包以满足您的要求,这不是谷歌官方包。它会根据 API 的 5K 字符限制自动发出多个请求,并将生成的音频连接到单个音频文件中。在执行代码之前,安装以下客户端库:
npm install @google-cloud/text-to-speech
npm install google-text-to-speech-concat --save
通过在 API 的每个请求的 <p></p> 标记之间添加少于 5k 个字符来尝试以下代码。例如,如果您有 9K 个字符,则需要将其拆分为 2 个或更多请求,因此在 <p></p> 标签之间添加前 5K 个字符,然后在新的 <p></p> 标签之间添加剩余的 4k 个字符。因此,通过使用 google-text-to-speech-concat 包,API 返回的音频文件被连接成一个音频文件。
const textToSpeech =require('@google-cloud/text-to-speech');
const testSynthesize =require('google-text-to-speech-concat');
const fs = require('fs');
const path= require('path');
(async () => {
const request = {
voice: {
languageCode: 'en-US',
ssmlGender: 'FEMALE'
},
input: {
ssml: `
<speak>
<p>add less than 5k chars between paragraph tags</p>
<p>add less than 5k chars between paragraph tags</p>
</speak>`
},
audioConfig: {
audioEncoding: 'MP3'
}
};
try {
// Create your Text To Speech client
// More on that here: https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application
const textToSpeechClient = new textToSpeech.TextToSpeechClient({
keyFilename: path.join(__dirname, 'google-cloud-credentials.json')
});
// Synthesize the text, resulting in an audio buffer
const buffer = await testSynthesize.synthesize(textToSpeechClient, request);
// Handle the buffer
// For example write it to a file or directly upload it to storage, like S3 or Google Cloud Storage
const outputFile = path.join(__dirname, 'Output.mp3');
// Write the file
fs.writeFile(outputFile, buffer, 'binary', (err) => {
if (err) throw err;
console.log('Got audio!', outputFile);
});
} catch (err) {
console.log(err);
}
})();
解决方法 2
尝试使用以下代码将整个文本拆分为 5K 字符集并将它们发送到 API 进行转换。如您所知,这会创建多个音频文件。在执行代码之前,在您当前的工作目录中创建一个文件夹来存储输出的音频文件。
const textToSpeech = require('@google-cloud/text-to-speech');
const fs = require('fs');
const util = require('util');
// Creates a client
const client = new textToSpeech.TextToSpeechClient();
(async function () {
// The text to synthesize
var text = fs.readFileSync('./text.txt', 'utf8');
var newArr = text.match(/[^\.]+\./g);
var charCount = 0;
var textChunk = "";
var index = 0;
for (var n = 0; n < newArr.length; n++) {
charCount += newArr[n].length;
textChunk = textChunk + newArr[n];
console.log(charCount);
if (charCount > 4600 || n == newArr.length - 1) {
console.log(textChunk);
// Construct the request
const request = {
input: {
text: textChunk
},
// Select the language and SSML voice gender (optional)
voice: {
languageCode: 'en-US',
ssmlGender: 'MALE',
name: "en-US-Wavenet-B"
},
// select the type of audio encoding
audioConfig: {
effectsProfileId: [
"headphone-class-device"
],
pitch: -2,
speakingRate: 1.1,
audioEncoding: "MP3"
},
};
// Performs the text-to-speech request
const [response] = await client.synthesizeSpeech(request);
console.log(response);
// Write the binary audio content to a local file
const writeFile = util.promisify(fs.writeFile);
await writeFile('result/Output' + index + '.mp3', response.audioContent, 'binary');
console.log('Audio content written to file: output.mp3');
index++;
charCount = 0;
textChunk = "";
}
}
}());
要将输出的音频文件合并为一个音频文件,可以使用audioconcat 包,它不是谷歌官方包。您还可以使用其他类似的可用包来连接音频文件。
要使用这个 audioconcat 库,需要已经安装了 ffmpeg 应用程序(不是 ffmpeg NPM 包)。因此,请根据您的操作系统安装ffmpeg 工具,并在执行连接音频文件的代码之前安装以下客户端库:
npm install audioconcat
npm install ffmpeg --enable-libmp3lame
试试下面的代码,它会连接您输出目录中的所有音频文件,并将单个连接的 output.mp3 音频文件存储在您当前的工作目录中。
const audioconcat = require('audioconcat')
const testFolder = 'result/';
const fs = require('fs');
var array=[];
fs.readdirSync(testFolder).forEach(songs => {
array.push("result/"+songs);
console.log(songs);
});
audioconcat(array)
.concat('output.mp3')
.on('start', function (command) {
console.log('ffmpeg process started:', command)
})
.on('error', function (err, stdout, stderr) {
console.error('Error:', err)
console.error('ffmpeg stderr:', stderr)
})
.on('end', function (output) {
console.error('Audio successfully created', output)
})
对于这两种解决方法,我测试了来自各种 GitHub 链接的代码,并根据您的要求修改了代码。以下是供您参考的链接。
- Workaround-1
- Workaround-2