🚀 Auto-deploy: Camila atualizado em 26/05/2026 13:07:23
This commit is contained in:
+38
-16
@@ -239,18 +239,36 @@ const initApp = () => {
|
||||
loadVoices().then(voices => { cachedVoices = voices; });
|
||||
|
||||
// Escolher melhor voz feminina brasileira disponível
|
||||
// Prioridade: Google pt-BR > Microsoft Natural > qualquer feminina > qualquer pt-BR
|
||||
const getBestBRVoice = () => {
|
||||
const brVoices = cachedVoices.filter(v => v.lang.includes('pt'));
|
||||
// Prioridade: feminina > masculino, local > remote
|
||||
const female = brVoices.find(v =>
|
||||
/female|brasil|maria|luciana|fernanda|virtual/i.test(v.name)
|
||||
);
|
||||
const brVoices = cachedVoices.filter(v => v.lang === 'pt-BR' || v.lang === 'pt_BR');
|
||||
|
||||
if (brVoices.length === 0) {
|
||||
// Fallback: qualquer voz portuguesa
|
||||
const ptVoices = cachedVoices.filter(v => v.lang.startsWith('pt'));
|
||||
return ptVoices[0] || null;
|
||||
}
|
||||
|
||||
// 1. Melhor: vozes Google (muito naturais no Chrome/Android)
|
||||
const google = brVoices.find(v => /google/i.test(v.name) && /femin|female/i.test(v.name));
|
||||
if (google) return google;
|
||||
const googleAny = brVoices.find(v => /google/i.test(v.name));
|
||||
if (googleAny) return googleAny;
|
||||
|
||||
// 2. Microsoft Natural / Online (Edge tem vozes excelentes como Francisca)
|
||||
const msNatural = brVoices.find(v => /natural|online|francisca|thalita|giovanna/i.test(v.name));
|
||||
if (msNatural) return msNatural;
|
||||
|
||||
// 3. Qualquer voz feminina explícita
|
||||
const female = brVoices.find(v => /female|femin|maria|luciana|fernanda|raquel|camila/i.test(v.name));
|
||||
if (female) return female;
|
||||
// fallback: qualquer voz brasileira
|
||||
const brazil = brVoices.find(v => /brasil|brazil|pt-BR/i.test(v.lang));
|
||||
if (brazil) return brazil;
|
||||
// fallback: qualquer voz portuguesa
|
||||
return brVoices[0] || null;
|
||||
|
||||
// 4. Vozes locais (melhor que remotas genéricas)
|
||||
const local = brVoices.find(v => v.localService === true);
|
||||
if (local) return local;
|
||||
|
||||
// 5. Qualquer voz pt-BR disponível
|
||||
return brVoices[0];
|
||||
};
|
||||
|
||||
// Falar texto com TTS nativo
|
||||
@@ -268,16 +286,20 @@ const initApp = () => {
|
||||
|
||||
// Limpar markdown básico antes de falar
|
||||
const clean = text
|
||||
.replace(/```[\s\S]*?```/g, 'trecho de código ignorado')
|
||||
.replace(/`[^`]+`/g, '')
|
||||
.replace(/[*_#~\[\]]/g, '')
|
||||
.replace(/\n+/g, ' ')
|
||||
.replace(/```[\s\S]*?```/g, '') // remover blocos de código inteiros
|
||||
.replace(/`[^`]+`/g, '') // remover inline code
|
||||
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') // links → só texto
|
||||
.replace(/[*_#~\[\]>]/g, '') // remover formatação
|
||||
.replace(/\n+/g, '. ') // quebras viram pausas naturais
|
||||
.replace(/\s{2,}/g, ' ')
|
||||
.trim();
|
||||
|
||||
if (!clean) return;
|
||||
|
||||
const utterance = new window.SpeechSynthesisUtterance(clean);
|
||||
utterance.lang = 'pt-BR';
|
||||
utterance.rate = 0.95;
|
||||
utterance.pitch = 1.05;
|
||||
utterance.rate = 1.12; // levemente mais rápida que o padrão
|
||||
utterance.pitch = 1.0; // tom natural sem distorção
|
||||
|
||||
const voice = getBestBRVoice();
|
||||
if (voice) utterance.voice = voice;
|
||||
|
||||
Reference in New Issue
Block a user