Communitygithub.com

TTS Local (Local TTS)

Gere voz humana localmente na sua GPU (ou CPU), sem custo de API — narrações, dublagens para vídeos explicativos, leitura de texto em voz alta e clipes de áudio a partir de texto, além de legendas .srt combinadas com os tempos das falas.

O que é TTS Local (Local TTS)?

O skill **Local TTS** permite que um agente de IA (como Claude Code, Cursor ou Codex) converta texto em fala humana de alta qualidade utilizando apenas o hardware local do usuário, sem depender de APIs pagas ou serviços na nuvem. Ele utiliza o modelo Qwen3-TTS 1.7B (quantizado em 8-bit GGUF, Q8_0) executado pelo motor C++ `qwentts.cpp`, que oferece desempenho em tempo real (~4x mais rápido) mesmo em GPUs modestas (ex.: RTX 4070 8 GB). O skill gera arquivos WAV de 24 kHz mono com opções de controle de estilo (tom da voz, pausas) e produção automática de legendas .srt sincronizadas com o áudio. Ele é ideal para narrações em vídeos explicativos, dublagens de projetos Remotion/fframes/HyperFrames, ou qualquer tarefa que precise de uma voz natural sem custos recorrentes. Além disso, inclui mecanismos para auditar a qualidade da geração (evitando erros de pronúncia de letras isoladas ou tokens incomuns) e um processo de atualização contínua que recomenda verificar periodicamente se há modelos mais recentes no ecossistema open-weight de TTS local.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Ayushmaniar/claude-explainer-skills/tree/HEAD/plugins/explainer-skills/skills/local-tts

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

O que TTS Local (Local TTS) faz?

A voz padrão: Qwen3-TTS 1.7B CustomVoice, locutor aiden, 8-bit GGUF (Q8_0), executado por qwentts.cpp (C++/ggml, MIT) com esta instrução de estilo:

Calorosa, clara e curiosa, como um narrador amigável de vídeo explicativo. Ritmo relaxado e constante.

Ele venceu um teste cego de escuta contra Kokoro, Chatterbox, PyTorch Qwen3-TTS, VoxCPM2 e Phonon (veja references/benchmarks.md). Em uma GPU Laptop RTX 4070 de 8 GB, roda a ~4x o tempo real, incluindo carregamento do modelo: uma narração de 18 minutos leva ~4,5 minutos.

Configuração (uma vez por máquina)

Execute python -I <skill>/scripts/say.py --check primeiro. Se imprimir OK, pule esta seção. Caso contrário, configure o motor, ou peça ao usuário para fazê-lo. Leva de 10 a 20 minutos e ~2,5 GB de disco.

  1. Compilar qwentts.cpp. Não existe binário pré-compilado para Windows, então compile a partir do código fonte:
    git clone --recurse-submodules https://github.com/ServeurpersoCom/qwentts.cpp ~/tools/qwentts.cpp
    cd ~/tools/qwentts.cpp
    ./buildcuda.sh       # NVIDIA (Linux); ./buildvulkan.sh para AMD/Intel; ./buildcpu.sh apenas CPU (ex.: macOS)
    
    No Windows, instale as Ferramentas de Build do VS 2022 (ou mais recente) com a carga de trabalho C++, CMake, Ninja e o CUDA Toolkit, depois execute buildcuda.cmd a partir do repositório. Se vcvars64.bat estiver em outro local, edite o caminho no topo desse script. Para segmentar apenas uma GPU, adicione -DCMAKE_CUDA_ARCHITECTURES=89 (RTX 40xx; 86 = RTX 30xx, 120 = RTX 50xx) à linha do cmake.
  2. Baixar os pesos (~2 GB) do Hugging Face Serveurperso/Qwen3-TTS-GGUF:
    pip install -U huggingface_hub
    hf download Serveurperso/Qwen3-TTS-GGUF qwen-talker-1.7b-customvoice-Q8_0.gguf qwen-tokenizer-12hz-Q8_0.gguf --local-dir ~/tools/qwen-gguf
    
  3. Apontar say.py para eles se você usou outras pastas: defina QWEN_TTS_HOME (o checkout), QWEN_TTS_EXE (o binário) ou QWEN_TTS_MODELS (a pasta .gguf). No Windows, say.py adiciona %CUDA_PATH%\bin\x64 ao PATH para você (substitua com CUDA_BIN).
  4. Execute say.py --check novamente e depois gere uma linha de teste.

Hardware: 8 GB de VRAM são suficientes para Q8_0 (~3 GB em uso). Sem GPU, uma compilação para CPU funciona a aproximadamente um quarto da velocidade. GGML_BACKEND=CPU força uma compilação GPU a rodar na CPU.

Antes de gerar

  1. Há algo mais usando a GPU? Um jogo ou outro aplicativo pesado na GPU torna a geração ~4x mais lenta e faz esse aplicativo travar. Pergunte antes de iniciar um trabalho longo. Se o usuário nomear tais aplicativos, defina TTS_BUSY_APPS=app1,app2 e say.py avisará quando um estiver em execução.
  2. Vale a pena verificar um modelo mais novo? Veja "Continue procurando por modelos melhores" abaixo. Se a última verificação tiver mais de ~6 semanas e a tarefa for uma narração real (não um teste de uma linha), faça a varredura rápida primeiro.
  3. O texto soa humano? Uma voz lê jargão de IA com a mesma entonação sempre, então o padrão se destaca mais do que no papel. Para qualquer narração com mais de algumas linhas, leia natural-narration.md do skill whiteboard-explainer (mesmo plugin, references/) e execute seu scripts/aispeak_scan.py, que aceita um script.py ou um arquivo de texto simples.

Gerar

O script usa apenas a biblioteca padrão, então qualquer Python 3.10+ funciona. <skill> é a pasta deste skill.

python -I <skill>/scripts/say.py "Primeira linha." "Segunda linha." -o saida.wav       # um WAV, lacunas de 0,35 s
python -I <skill>/scripts/say.py --file linhas.txt -o clips/                          # 000.wav, 001.wav, ...

Opções:

FlagO que faz
--speakeraiden (padrão); ryan é a outra voz nativa em inglês
--instructTexto de estilo, ex.: "Animado, ritmo acelerado" ou "Calmo e sério"
--seed NGera uma tomada repetível
--gap SSegundos de silêncio entre linhas em um arquivo unido
--srt FTambém escreve legendas sincronizadas com o WAV unido (veja Legendas)
--quantQ8_0 (padrão, melhor) ou Q4_K_M (menor, um pouco mais plano; baixe-o primeiro)
--checkReporta o motor, modelos e pastas CUDA encontrados

Como funciona:

  • Cada linha passa por um único processo, então o modelo carrega uma vez (3–8 s). Passe linhas em lote, não uma chamada por linha.
  • A saída é WAV mono de 24 kHz, 16 bits.

As tomadas são amostradas, então cada execução difere:

  • Mantenha os clipes de que gostar. Cache por linha, indexado por texto mais configurações.
  • Refazer uma linha se seu comprimento estiver muito distante de ~0,07 s por caractere. Isso significa que palavras foram descartadas ou inventadas.

Para uma narração em vídeo, também:

  • Aparar o silêncio de cada clipe para ~50 ms de preenchimento e, em seguida, posicione as linhas na linha do tempo com seus próprios intervalos.
  • Normalizar o volume da faixa final: ffmpeg -af loudnorm=I=-16:TP=-1.5:LRA=11.

Legendas (.srt): ofereça-as com cada vídeo narrado

Você já sabe quando cada linha começa e termina, então não há nada para transcrever. Construa as legendas a partir desses tempos.

  • Com say.py: adicione --srt narracao.srt (precisa de um .wav -o). As legendas correspondem exatamente à faixa unida.
  • Em seu próprio pipeline: chame scripts/srt.py, to_srt([(inicio_s, fim_s, texto), ...], exibir=[...]), com início/fim em tempo de vídeo por linha falada. Ou use a CLI: python srt.py tempos.tsv -o video.srt.
  • Corrigir grafias da voz. O texto da narração é frequentemente escrito para a voz: "D I L", nomes reescritos foneticamente, "runner ponto HTML", números por extenso. Mapeie-os de volta com display / --display exibir.tsv (faladoescrito). Use as formas escritas do que é mostrado na tela e use algarismos para números ("$232", "83%").
  • Verifique o resultado. Pesquise por letras maiúsculas espaçadas restantes ([A-Z] [A-Z]) e " ponto ".
  • Regras que o módulo aplica:
    • no máximo 2 linhas de 42 caracteres por legenda
    • quebra em frase, depois em oração, depois em palavra
    • frases curtas mescladas para que nada passe rápido demais
    • tempo dividido proporcionalmente ao comprimento
  • Nomeie como o vídeo (Nome do Video.srt ao lado de Nome do Video.mp4) para que os players o carreguem automaticamente. No VLC, --sub-file= força um arquivo.

O skill whiteboard-explainer contém em template/narration/build_vo.py um pipeline completo:

cache por linha, refilmagens, corte de silêncio, modelagem de pausas, alinhamento de palavras, tabela de dicas e envelope de sincronização labial.

Armadilhas

  • As DLLs CUDA devem estar no PATH (Windows). O CUDA 13 as mantém em ...\CUDA\v13.x\bin\x64. Sem essa pasta no PATH, qwen-tts.exe termina silenciosamente sem saída. say.py adiciona para você.
  • --stream-by-line -o - escreve cabeçalhos WAV streaming (tamanhos 0x7fffffff), um por linha. Divida em RIFF....WAVEfmt e descarte cada cabeçalho de 44 bytes. Não confie nos campos de tamanho.
  • Aiden lê mal letras soltas e tokens estranhos. Descoberto por uma auditoria não solicitada do Whisper:
    • "h star" saiu como "a hap" ou "our star", "y t" como "VT", "y" como "we", e "arXiv" como "ArcSireFolk".
    • Funcionam: "H star" maiúsculo / "under H", "why tee" / "why tilde", "archive", e "SMILES check".
    • "aitch" é errático. Um nome pode funcionar sozinho e ser distorcido no meio da frase: teste dentro da linha inteira.
    • Um K inicial de frase pode cair ("Kwenputer" → "When Pooter"): comece essas linhas com "And" ou "So".
    • Audite transcrevendo cada clipe sem o script como prompt inicial e depois compare com o script. Um Whisper com prompt "ouve" as palavras pretendidas e esconde os erros. Ferramentas: whiteboard-explainer/template/narration/audit_vo.py e tts_try.py.
  • Pausas em dois-pontos. O Qwen pausa 0,6-0,8 s em um dois-pontos e às vezes no meio da frase. Em uma narração, limite cada silêncio pela pontuação anterior (shape() no build_vo.py do template) e evite linhas fragmentadas com dois-pontos ("Primeiro: ...").
  • Fallback para CPU: Kokoro 82M (kokoro-onnx) é monótono, mas rápido na CPU, adequado para rascunhos enquanto a GPU estiver ocupada.

Continue procurando por modelos melhores

O TTS local está melhorando rapidamente, e a escolha atual será superada. Trate-a como a campeã atual, não como a resposta final. Procure por modelos mais novos e melhores, especialmente antes de um grande trabalho de narração ou quando a última verificação abaixo tiver mais de ~6 semanas.

  1. Varredura. Pesquise na web por modelos TTS de pesos abertos lançados ou atualizados desde a última verificação. Veja:
    • TTS Arena / Artificial Analysis speech leaderboards
    • Hugging Face trending text-to-speech models
    • r/LocalLLaMA
    • Lançamentos no GitHub dos motores abaixo
  2. Filtrar. Mantenha um candidato apenas se ele:
    • puder ser usado localmente gratuitamente (pesos abertos, licença permissiva ou de uso pessoal)
    • rodar na memória GPU e sistema operacional do usuário
    • falar o idioma necessário
    • superar o campeão em qualidade, ou igualá-lo sendo muito mais rápido
  3. Teste. Gere eval/linhas.txt com o candidato. Pontue-o contra o campeão com scripts/voice_metrics.py (pip install numpy librosa; as gravações do campeão e baseline estão em eval/):
    • Desvio padrão da altura (pitch) ≥ ~5 semitons e alcance ≥ ~17 semitons são necessários para soar natural.
    • Meça a velocidade como segundos de áudio por segundo de geração.
  4. Ouça. Peça ao usuário para escolher de ouvido entre o candidato e eval/champion_*.wav (ffplay -nodisp -autoexit arquivo.wav). As métricas apenas pré-selecionam candidatos; o ouvido decide.
  5. Registre. Atualize a linha "Última verificação" abaixo e references/benchmarks.md, independentemente de algo ter mudado. Se o campeão mudar, substitua eval/champion_*.wav e atualize say.py, e pergunte antes de excluir o modelo antigo.

Última verificação: 2026-11-02 (pesquisa na web mais testes locais com VoxCPM2 Q8 e Phonon 31m/Miles). Aiden foi preferido de ouvido em relação a ambos. Ainda não testado localmente: Phonon 40m, OmniVoice, Breeze TTS 2, Drama 3, Orpheus, Dia, Sesame CSM, Spark-TTS, IndexTTS-2, VibeVoice, Higgs Audio, Kyutai TTS e Fish/OpenAudio. Detalhes em references/benchmarks.md.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Habilidades Relacionadas