mirror of
https://github.com/jambonz/speech-utils.git
synced 2026-07-23 12:41:48 +00:00
trim trailing silence from azure tts when JAMBONES_TTS_TRIM_SILENCE is set
This commit is contained in:
+31
-3
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user