🚀 Auto-deploy: Camila atualizado em 26/05/2026 13:59:50

This commit is contained in:
2026-05-26 13:59:50 +00:00
parent ace6c53448
commit 71e633ce71
316 changed files with 59354 additions and 86 deletions
+60
View File
@@ -343,6 +343,66 @@ app.post('/api/chat', requireAuth, async (req, res) => {
}
});
// ==========================================================================
// TTS — Text-to-Speech com voz neural Microsoft (Thalita)
// ==========================================================================
const { MsEdgeTTS } = require('msedge-tts');
const TTS_VOICE = 'pt-BR-ThalitaMultilingualNeural';
const TTS_FORMAT = 'audio-24khz-96kbitrate-mono-mp3';
// Instância TTS reutilizável (inicializada no primeiro uso)
let ttsInstance = null;
const getTTS = async () => {
if (!ttsInstance) {
ttsInstance = new MsEdgeTTS();
await ttsInstance.setMetadata(TTS_VOICE, TTS_FORMAT);
}
return ttsInstance;
};
// Pré-inicializar TTS ao iniciar o servidor
getTTS().then(() => console.log(`TTS inicializado com voz: ${TTS_VOICE}`))
.catch(err => console.warn('Aviso: TTS não pôde ser pré-inicializado:', err.message));
app.post('/api/tts', requireAuth, async (req, res) => {
const { text } = req.body;
if (!text || typeof text !== 'string') {
return res.status(400).json({ error: 'Texto é obrigatório' });
}
// Limitar tamanho do texto para evitar abusos
const cleanText = text.substring(0, 5000);
try {
const tts = await getTTS();
const result = await tts.toStream(cleanText);
res.setHeader('Content-Type', 'audio/mpeg');
res.setHeader('Cache-Control', 'no-cache');
result.audioStream.pipe(res);
result.audioStream.on('error', (err) => {
console.error('Erro no stream TTS:', err);
// Tentar reinicializar a instância TTS na próxima vez
ttsInstance = null;
if (!res.headersSent) {
res.status(500).json({ error: 'Erro ao gerar áudio' });
}
});
} catch (error) {
console.error('Erro na rota TTS:', error);
// Reinicializar instância para a próxima tentativa
ttsInstance = null;
if (!res.headersSent) {
res.status(500).json({ error: 'Erro ao gerar áudio' });
}
}
});
// Rota coringa para redirecionar para index.html
app.get('*', requireAuth, (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));