This commit is contained in:
Hoan HL
2026-01-14 13:51:32 +07:00
parent 6b2b35acfb
commit 0e33358254
2 changed files with 262 additions and 4 deletions
+42 -4
View File
@@ -205,7 +205,8 @@ async function synthAudio(client, createHash, retrieveHash, logger, stats, { acc
switch (vendor) {
case 'google':
audioData = await synthGoogle(logger, {
credentials, stats, language, voice, gender, key, text, model, options, instructions
credentials, stats, language, voice, gender, key, text, model, options, instructions,
renderForCaching, disableTtsStreaming, disableTtsCache
});
break;
case 'aws':
@@ -413,12 +414,49 @@ const synthPolly = async(createHash, retrieveHash, logger,
const synthGoogle = async(logger, {
credentials, stats, language, voice, gender, text, model, options, instructions
credentials, stats, language, voice, gender, key, text, model, options, instructions,
renderForCaching, disableTtsStreaming, disableTtsCache
}) => {
const client = new ttsGoogle.TextToSpeechClient(credentials);
const isGemini = !!model;
const isVoiceCloning = typeof voice === 'object' && voice.voice_cloning_key;
// HD voices have pattern like en-US-Chirp3-HD-Charon
const isHDVoice = typeof voice === 'string' && voice.includes('-HD-');
// Live API is used for Gemini TTS and HD voices
const useLiveApi = isGemini || isHDVoice;
// Streaming support for Google TTS (Gemini, HD voices, and standard voices)
// Voice cloning does not support streaming
if (!isVoiceCloning && !JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching && !disableTtsStreaming) {
// Strip SSML tags for Gemini TTS (it doesn't support SSML)
let inputText = text;
if (isGemini && text.startsWith('<speak>')) {
inputText = text.replace(/<[^>]*>/g, '').trim();
logger.info('synthGoogle: Gemini TTS does not support SSML, stripped tags from input');
}
let params = '{';
params += `credentials=${JSON.stringify(credentials)}`;
params += `,playback_id=${key}`;
params += ',vendor=google';
params += `,voice=${voice}`;
params += `,language_code=${language || 'en-US'}`;
params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
params += `,use_live_api=${useLiveApi ? 1 : 0}`;
if (model) params += `,model_name=${model}`;
if (gender) params += `,gender=${gender}`;
// comma is used to separate parameters in freeswitch tts module
const prompt = options?.prompt || instructions;
if (prompt) params += `,prompt=${prompt.replace(/\n/g, ' ').replace(/,/g, ';')}`;
params += '}';
return {
filePath: `say:${params}${(isGemini ? inputText : text).replace(/\n/g, ' ')}`,
servedFromCache: false,
rtt: 0
};
}
const client = new ttsGoogle.TextToSpeechClient(credentials);
// Build input based on voice type
let input;