
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
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
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
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
Flags que valem conhecer (python3 -m piper --help mostra todas):
-
--length-scale 1.1deixa a fala mais lenta;0.9acelera -
--sentence-silence 0.3coloca pausa entre frases -
--volume 1.2aumenta 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]}")
printf "Primeira frase do roteiro.\nSegunda frase, um pouco mais longa, pra testar o ritmo.\n" > roteiro2.txt
python3 narrar.py roteiro2.txt
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
Pra conferir quanto deu:
ffmpeg -i narracao_final.wav -af ebur128 -f null - 2>&1 | grep -A1 Integrated
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
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
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)