DEV Community

Cover image for Narração em português com IA, de graça, no Linux (Piper TTS + ffmpeg)
Nuvem Dev
Nuvem Dev

Posted on

Narração em português com IA, de graça, no Linux (Piper TTS + ffmpeg)

Short de 32 s narrado com Piper
Esse short de 32 segundos foi narrado inteiro com o que tá nesse tutorial. Clica pra ver (ele roda na newsletter).

Eu precisava de narração em português pros meus vídeos curtos e não queria depender de API paga logo de cara. A saída foi o Piper: um TTS open source (GPL-3.0) que roda offline, na CPU, e tem voz pt-BR.

Aqui vai o caminho que eu usei, do zero até um mp4 vertical. Rodei tudo isso num Debian, com Python 3.12, em outubro de 2026, com o piper-tts 1.8.0.

1. Instalar

Cria uma venv pra não bagunçar o Python do sistema:

mkdir narracao && cd narracao
python3 -m venv .venv
source .venv/bin/activate
pip install piper-tts
Enter fullscreen mode Exit fullscreen mode

Não precisa de GPU. O pacote já vem com o que ele usa pra fonemas (espeak-ng embutido).

2. Baixar a voz pt-BR

A voz brasileira que eu uso é a faber, qualidade medium (dataset CC0, segundo o model card):

python3 -m piper.download_voices pt_BR-faber-medium
Enter fullscreen mode Exit fullscreen mode

Isso baixa dois arquivos na pasta atual: pt_BR-faber-medium.onnx (uns 63 MB) e o .onnx.json de config. Os dois precisam ficar juntos.

3. Primeiro áudio

echo "Fala, pessoal! Essa narração foi gerada de graça, rodando no meu servidor." > roteiro.txt
python3 -m piper -m pt_BR-faber-medium.onnx -i roteiro.txt -f narracao.wav
Enter fullscreen mode Exit fullscreen mode

Aqui levou menos de 2 segundos pra gerar uns 4 segundos de áudio, na CPU. Confere o arquivo:

ffprobe -v error -show_entries format=duration:stream=sample_rate,channels -of default=nw=1 narracao.wav
# sample_rate=22050
# channels=1
# duration=4.179592
Enter fullscreen mode Exit fullscreen mode

Flags que valem conhecer (python3 -m piper --help mostra todas):

  • --length-scale 1.1 deixa a fala mais lenta; 0.9 acelera
  • --sentence-silence 0.3 coloca pausa entre frases
  • --volume 1.2 aumenta o volume

4. Em lote, com Python

Pra vídeo eu gosto de gerar um arquivo por cena, porque fica fácil sincronizar legenda e imagem depois. Uma linha do roteiro = uma cena:

# narrar.py
import sys, wave
from piper import PiperVoice, SynthesisConfig

voz = PiperVoice.load("pt_BR-faber-medium.onnx")
cfg = SynthesisConfig(length_scale=0.95)  # < 1 = fala mais rápido

with open(sys.argv[1], encoding="utf-8") as f:
    blocos = [l.strip() for l in f if l.strip()]

for i, texto in enumerate(blocos, 1):
    with wave.open(f"parte_{i:02d}.wav", "wb") as wav:
        voz.synthesize_wav(texto, wav, syn_config=cfg)
    print(f"parte_{i:02d}.wav  <- {texto[:40]}")
Enter fullscreen mode Exit fullscreen mode
printf "Primeira frase do roteiro.\nSegunda frase, um pouco mais longa, pra testar o ritmo.\n" > roteiro2.txt
python3 narrar.py roteiro2.txt
Enter fullscreen mode Exit fullscreen mode

Dica de quem apanhou: nome de marca em inglês ele lê do jeito dele. Eu mantenho duas versões do texto, uma pra legenda ("ElevenLabs") e outra pra voz, escrita do jeito que eu quero ouvir ("Íleven Labs").

5. Juntar e normalizar o volume

Plataforma de vídeo curto costuma trabalhar perto de -14 LUFS. O loudnorm do ffmpeg resolve:

for f in parte_*.wav; do echo "file '$f'"; done > lista.txt
ffmpeg -f concat -safe 0 -i lista.txt \
  -af loudnorm=I=-14:TP=-1.5:LRA=11 -ar 44100 narracao_final.wav
Enter fullscreen mode Exit fullscreen mode

Pra conferir quanto deu:

ffmpeg -i narracao_final.wav -af ebur128 -f null - 2>&1 | grep -A1 Integrated
Enter fullscreen mode Exit fullscreen mode

Num clipe curto o loudnorm de uma passada fica um pouco abaixo do alvo (aqui deu -14,9). Pra short isso tá ok; se quiser cravar, faz o loudnorm em duas passadas.

6. Virar vídeo vertical

O mínimo: uma imagem 1080x1920 + a narração.

ffmpeg -loop 1 -i capa.png -i narracao_final.wav \
  -vf "scale=1080:1920,format=yuv420p" -r 30 \
  -c:v libx264 -tune stillimage -c:a aac -b:a 160k \
  -shortest video.mp4
Enter fullscreen mode Exit fullscreen mode
ffprobe -v error -show_entries stream=codec_name,width,height,r_frame_rate -of compact video.mp4
# stream|codec_name=h264|width=1080|height=1920|r_frame_rate=30/1
# stream|codec_name=aac|r_frame_rate=0/0
Enter fullscreen mode Exit fullscreen mode

No meu pipeline eu vou além disso (uma cena por imagem com zoom lento via zoompan, legenda em .ass queimada com o filtro ass=), mas o esqueleto é esse aí.

Limites, sendo sincero

A voz é boa pra tutorial e pra testar formato. Mas a entonação é mais reta que a dos serviços pagos e às vezes escorrega numa palavra. Se o projeto pede voz bem natural, ou clonar a sua, aí vale olhar ElevenLabs ou Murf. Eu comparei preço por minuto das duas (e da Fish Audio, que hoje não lista português no TTS) nessa edição da newsletter.

Se travar em algum passo, comenta aqui com o erro que eu tento ajudar.


Alguns links da newsletter são de afiliado: se você comprar, eu ganho uma comissão e você não paga nada a mais.

Top comments (0)