trim trailing silence from azure tts when JAMBONES_TTS_TRIM_SILENCE is set

This commit is contained in:
Dave Horton
2023-07-19 09:59:34 -04:00
parent 38c3219425
commit 830be783b8
+31 -3
View File
@@ -33,6 +33,24 @@ const debug = require('debug')('jambonz:realtimedb-helpers');
const EXPIRES = (process.env.JAMBONES_TTS_CACHE_DURATION_MINS || 4 * 60) * 60; // cache tts for 4 hours
const TMP_FOLDER = '/tmp';
const trimTrailingSilence = (buffer) => {
assert.ok(buffer instanceof Buffer, 'trimTrailingSilence - argument is not a Buffer');
let offset = buffer.length;
while (offset > 0) {
// Get 16-bit value from the buffer (read in reverse)
const value = buffer.readUInt16BE(offset - 2);
if (value !== 0) {
break;
}
offset -= 2;
}
// Trim the silence from the end
return offset === buffer.length ? buffer : buffer.subarray(0, offset);
};
/**
* Synthesize speech to an mp3 file, and also cache the generated speech
* in redis (base64 format) for 24 hours so as to avoid unnecessarily paying
@@ -104,7 +122,12 @@ async function synthAudio(client, logger, stats, { account_sid,
text
});
let filePath;
if (['nuance', 'nvidia'].includes(vendor)) {
if (['nuance', 'nvidia'].includes(vendor) ||
(
process.env.JAMBONES_TTS_TRIM_SILENCE &&
['microsoft', 'azure'].includes(vendor)
)
) {
filePath = `${TMP_FOLDER}/${key.replace('tts:', `tts-${salt || ''}`)}.r8`;
}
else filePath = `${TMP_FOLDER}/${key.replace('tts:', `tts-${salt || ''}`)}.mp3`;
@@ -284,6 +307,7 @@ const synthMicrosoft = async(logger, {
}) => {
try {
const {api_key: apiKey, region, use_custom_tts, custom_tts_endpoint} = credentials;
const trimSilence = filePath.endsWith('.r8');
let content = text;
const speechConfig = SpeechConfig.fromSubscription(apiKey, region);
speechConfig.speechSynthesisLanguage = language;
@@ -297,7 +321,9 @@ const synthMicrosoft = async(logger, {
*/
if (!content.startsWith('<speak')) content = `<speak>${text}</speak>`;
}
speechConfig.speechSynthesisOutputFormat = SpeechSynthesisOutputFormat.Audio16Khz32KBitRateMonoMp3;
speechConfig.speechSynthesisOutputFormat = trimSilence ?
SpeechSynthesisOutputFormat.Raw8Khz16BitMonoPcm :
SpeechSynthesisOutputFormat.Audio16Khz32KBitRateMonoMp3;
const synthesizer = new SpeechSynthesizer(speechConfig);
if (content.startsWith('<speak>')) {
@@ -323,7 +349,9 @@ const synthMicrosoft = async(logger, {
reject(cancellation.errorDetails);
break;
case ResultReason.SynthesizingAudioCompleted:
resolve(Buffer.from(result.audioData));
let buffer = Buffer.from(result.audioData);
if (trimSilence) buffer = trimTrailingSilence(buffer);
resolve(buffer);
synthesizer.close();
stats.increment('tts.count', ['vendor:microsoft', 'accepted:yes']);
break;