diff --git a/packages/server/src/controllers/text-to-speech/index.ts b/packages/server/src/controllers/text-to-speech/index.ts index 69a75d5ec..9786cde60 100644 --- a/packages/server/src/controllers/text-to-speech/index.ts +++ b/packages/server/src/controllers/text-to-speech/index.ts @@ -1,4 +1,5 @@ import { Request, Response, NextFunction } from 'express' +import chatflowsService from '../../services/chatflows' import textToSpeechService from '../../services/text-to-speech' import { InternalFlowiseError } from '../../errors/internalFlowiseError' import { StatusCodes } from 'http-status-codes' @@ -8,7 +9,16 @@ import { databaseEntities } from '../../utils' const generateTextToSpeech = async (req: Request, res: Response) => { try { - const { chatMessageId, text, provider, credentialId, voice, model } = req.body + const { + chatId, + chatflowId, + chatMessageId, + text, + provider: bodyProvider, + credentialId: bodyCredentialId, + voice: bodyVoice, + model: bodyModel + } = req.body if (!text) { throw new InternalFlowiseError( @@ -17,6 +27,35 @@ const generateTextToSpeech = async (req: Request, res: Response) => { ) } + let provider: string, credentialId: string, voice: string, model: string + + if (chatflowId) { + // Get TTS config from chatflow + const chatflow = await chatflowsService.getChatflowById(chatflowId) + const ttsConfig = JSON.parse(chatflow.textToSpeech) + + // Extract the first provider config (assuming single provider per chatflow) + const providerKey = Object.keys(ttsConfig)[0] + if (!providerKey) { + throw new InternalFlowiseError( + StatusCodes.BAD_REQUEST, + `Error: textToSpeechController.generateTextToSpeech - no TTS provider configured in chatflow!` + ) + } + + const providerConfig = ttsConfig[providerKey] + provider = providerKey + credentialId = providerConfig.credentialId + voice = providerConfig.voice + model = providerConfig.model + } else { + // Use TTS config from request body + provider = bodyProvider + credentialId = bodyCredentialId + voice = bodyVoice + model = bodyModel + } + if (!provider) { throw new InternalFlowiseError( StatusCodes.BAD_REQUEST, @@ -40,8 +79,8 @@ const generateTextToSpeech = async (req: Request, res: Response) => { const appServer = getRunningExpressApp() const options = { orgId: '', - chatflowid: '', - chatId: '', + chatflowid: chatflowId || '', + chatId: chatId || '', appDataSource: appServer.AppDataSource, databaseEntities: databaseEntities } diff --git a/packages/server/src/services/chatflows/index.ts b/packages/server/src/services/chatflows/index.ts index e97e7deb0..774fda045 100644 --- a/packages/server/src/services/chatflows/index.ts +++ b/packages/server/src/services/chatflows/index.ts @@ -357,7 +357,18 @@ const getSinglePublicChatbotConfig = async (chatflowId: string): Promise => if (dbResponse.chatbotConfig || uploadsConfig) { try { const parsedConfig = dbResponse.chatbotConfig ? JSON.parse(dbResponse.chatbotConfig) : {} - return { ...parsedConfig, uploads: uploadsConfig, flowData: dbResponse.flowData } + const ttsConfig = + typeof dbResponse.textToSpeech === 'string' ? JSON.parse(dbResponse.textToSpeech) : dbResponse.textToSpeech + + let isTTSEnabled = false + if (ttsConfig) { + Object.keys(ttsConfig).forEach((provider) => { + if (ttsConfig?.[provider]?.status) { + isTTSEnabled = true + } + }) + } + return { ...parsedConfig, uploads: uploadsConfig, flowData: dbResponse.flowData, isTTSEnabled } } catch (e) { throw new InternalFlowiseError(StatusCodes.INTERNAL_SERVER_ERROR, `Error parsing Chatbot Config for Chatflow ${chatflowId}`) } diff --git a/packages/ui/src/views/chatmessage/ChatMessage.jsx b/packages/ui/src/views/chatmessage/ChatMessage.jsx index 0e6a47cc5..88788a5ba 100644 --- a/packages/ui/src/views/chatmessage/ChatMessage.jsx +++ b/packages/ui/src/views/chatmessage/ChatMessage.jsx @@ -1342,7 +1342,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP let isEnabled = false if (ttsConfig) { Object.keys(ttsConfig).forEach((provider) => { - if (ttsConfig[provider] && ttsConfig[provider].status && ttsConfig[provider].credentialId) { + if (ttsConfig?.[provider]?.status) { isEnabled = true } }) @@ -1625,37 +1625,6 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP handleTTSStart({ chatMessageId: messageId, format: 'mp3' }) try { - let ttsConfig = null - if (getChatflowConfig?.data?.textToSpeech) { - try { - ttsConfig = - typeof getChatflowConfig.data.textToSpeech === 'string' - ? JSON.parse(getChatflowConfig.data.textToSpeech) - : getChatflowConfig.data.textToSpeech - } catch (error) { - console.error('Error parsing TTS config:', error) - } - } - - let activeProvider = null - let providerConfig = null - if (ttsConfig) { - Object.keys(ttsConfig).forEach((provider) => { - if (ttsConfig?.[provider]?.status) { - activeProvider = provider - providerConfig = ttsConfig[provider] - } - }) - } - - if (!activeProvider || !providerConfig || !providerConfig.credentialId) { - enqueueSnackbar({ - message: 'Text-to-speech is not configured for this chatflow', - options: { variant: 'warning' } - }) - return - } - const abortController = new AbortController() setTtsStreamingState((prev) => ({ ...prev, abortController })) @@ -1668,13 +1637,10 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP credentials: 'include', signal: abortController.signal, body: JSON.stringify({ + chatflowId: chatflowid, chatId: chatId, chatMessageId: messageId, - text: messageText, - provider: activeProvider, - credentialId: providerConfig.credentialId, - voice: providerConfig.voice, - model: providerConfig.model + text: messageText }) })