From ace6c53448d0d7c1c93227a7d2ed8b3616d40674 Mon Sep 17 00:00:00 2001 From: admtracksteel Date: Tue, 26 May 2026 13:07:23 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20Auto-deploy:=20Camila=20atualiza?= =?UTF-8?q?do=20em=2026/05/2026=2013:07:23?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/app.js | 54 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/public/app.js b/public/app.js index 2731675..788c9ea 100644 --- a/public/app.js +++ b/public/app.js @@ -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;