Pular para o conteúdo

· 15 min de leitura

Como construí um podcast com a minha voz clonada, do roteiro ao blog

O pipeline completo do fghisi podcast: notas, roteiro com o Claude, revisão em pull request, voz clonada na ElevenLabs, pós-produção no ffmpeg, releases do GitHub, Eleventy e um feed RSS. Com as ferramentas, os comandos, os custos e os erros que me custaram créditos.

Por que um podcast

Eu escrevo no blog sobre engenharia de software e liderança. Mas muita gente que eu queria alcançar não lê artigo longo. Ouve, no carro, na academia, enquanto lava a louça.

Gravar toda semana não cabia na minha rotina. Então eu quis testar uma ideia: e se o podcast nascesse do mesmo jeito que o código deste site? Notas minhas, um roteiro revisado num pull request e uma automação fazendo o resto.

O resultado é o fghisi podcast. Cada episódio parte de um livro, de um artigo meu ou de um aprendizado, e é narrado pela minha voz, clonada com inteligência artificial. As ideias e as opiniões são minhas. A IA me ajuda a transformar isso em áudio.

Antes de escrever uma linha de código, eu desenhei o pipeline inteiro num documento. Este artigo segue esse desenho, etapa por etapa, e conta o que mudou quando ele encontrou o mundo real.

O desenho do início

Este foi o primeiro desenho do pipeline, do jeito que ficou no documento antes de qualquer código. A ideia central já estava ali: eu atuo em dois pontos, as notas e a revisão, e o resto roda sozinho. Dois blocos, o clone da voz e o guia de voz, seriam configurados uma vez e reaproveitados em todos os episódios.

O desenho do início: eu atuo em dois pontos e o resto roda sozinho Eu atuo em dois pontos; o resto roda sozinho eu automático configurado uma vez 1. Notas do livro2. Roteiro3. Revisão no pull request 4. Áudio com a minha voz5. Pós-produção6. Publicação Clone da vozGuia de voz e prompt Eu escrevo as notasClaude gera o roteiro e as notas do episódio Eu ajusto e aprovoElevenLabs, bloco a bloco ffmpeg: vinheta, -16 LUFS, tags ID3MP3 publicado, página e feed RSS 1 a 3 h de gravaçãoMeu estilo, por escrito
O primeiro desenho do pipeline, antes de qualquer código: duas etapas minhas, quatro automáticas e dois blocos configurados uma vez.

Quase tudo isso foi construído. O que mudou no caminho está mais adiante, em "O plano e a realidade".

O fluxo de um episódio

O fluxo de um episódio: notas, roteiro, revisão, áudio e publicação NotasRoteiroRevisãoÁudioPublicação notas.md numabranch ep/… Claude + guiade voz leio em voz altano pull request ElevenLabs+ ffmpeg release, páginae feed RSS EUIAEUGITHUB ACTIONSDEPLOY DOIS PONTOS HUMANOS: AS NOTAS E A REVISÃO. O RESTO É AUTOMÁTICO.
O fluxo de um episódio: eu escrevo as notas e reviso o roteiro; o resto roda no GitHub Actions.

São seis etapas. Duas são minhas e as outras rodam sozinhas:

  1. Clonagem da voz, feita uma vez e reaproveitada em todos os episódios.
  2. Notas, um arquivo notas.md que eu escrevo numa branch ep/<data>-<tema>. É a única etapa totalmente manual, e é ela que garante que o episódio tem a minha opinião.
  3. Roteiro, escrito com o Claude a partir das notas e de um guia de voz.
  4. Revisão, no pull request. Eu leio o roteiro em voz alta e ajusto o que não soa como eu.
  5. Áudio: a voz é gerada na ElevenLabs e montada no ffmpeg, com volume padronizado e trilha.
  6. Publicação: o MP3 vai para um release do GitHub e o site ganha a página do episódio e o item no feed RSS.

O tempo humano por episódio fica em escrever as notas, cerca de uma hora depois de ler, e revisar o roteiro, uns vinte minutos.

A stack

A regra que eu me dei foi usar o que o site já tinha, sempre que desse. Esta é a stack que ficou, com as alternativas que considerei:

Etapa Ferramenta Alternativa considerada Por quê
Voz clonada ElevenLabs Resemble AI, modelos abertos (F5-TTS, Chatterbox) A voz mais natural em português que encontrei, com API simples
Roteiro Claude, da Anthropic Escrever à mão Segue o guia de voz e a estrutura de cada tipo de episódio com consistência
Notas Markdown no repositório Readwise, para puxar destaques do Kindle Versionado, sem custo, editável em qualquer lugar
Pós-produção ffmpeg Auphonic Gratuito e roda no GitHub Actions
Arquivos de áudio Releases de um repositório público no GitHub Cloudflare R2, pasta na Hostinger Sem conta nova, sem senha e sem custo
Site e feed Eleventy, o gerador deste blog Astro, um serviço de hospedagem de podcast O episódio vive no meu domínio e sai no mesmo build do blog
Orquestração GitHub Actions n8n, Make Já é o caminho do código do site, sem servidor extra

Os scripts são em Python, só com a biblioteca padrão. As chamadas às APIs são urllib puro, sem SDK. Isso deixou o pipeline fácil de testar sem rede e de rodar no meu computador.

O repositório ficou assim:

podcast/
  config/
    guia-de-voz.md      como eu falo: abertura, fechamento, ritmo, regras
    prompt.md           instruções do roteiro para cada tipo de episódio
    pronuncia.json      nomes e termos escritos como se leem
    trilha.mp3          a trilha de todo episódio
  episodios/
    _modelo/            modelos das notas: livro, artigo e aprendizado
    2026-10-de-senior-a-principal/
      notas.md          eu escrevo
      roteiro.md        gerado e revisado no PR
      notas-do-episodio.md
      linkedin.md
  scripts/              gerar_roteiro, sintetizar, pos_producao, publicar, remixar

Etapa 1: clonar a voz

A ElevenLabs oferece dois tipos de clone:

Opção Áudio necessário Qualidade Plano mínimo
Clone rápido (Instant Voice Clone) 1 a 3 minutos Boa para começar; perde naturalidade em áudios longos Starter
Clone profissional (Professional Voice Clone) 30 minutos, ideal 3 horas Quase indistinguível da voz original Creator

O plano era começar pelo clone rápido para validar o pipeline inteiro, enquanto eu juntava horas de gravação para o profissional. Quando ele ficasse pronto, bastaria trocar o voice_id. É o que estou fazendo.

Para a gravação, o roteiro que segui foi este:

  1. Ambiente: um cômodo silencioso, com cortinas, tapete ou roupas por perto para abafar o eco, e nada de ventilador ligado.
  2. Equipamento: microfone sempre na mesma distância, cerca de um palmo da boca.
  3. Formato: WAV, 44,1 ou 48 kHz, mono, sem música nem redução de ruído agressiva.
  4. Conteúdo: falar no tom do podcast, conversado, e não ler um texto. O clone copia o jeito da gravação: amostra lida dá clone com cara de leitura.

Etapa 2: as notas

Cada episódio nasce de um único arquivo. Tem um modelo para cada tipo de episódio. Este é o de artigo:

---
tipo: artigo
artigo: "De sênior a principal: o trabalho que acontece entre os times"
url: "https://fghisi.com.br/2026/10/16/de-senior-a-principal/"
minutos: 12
publicar_em: 2026-10-18
---

## Por que escrevi esse artigo
## O que quero que fique de quem ouvir (3 pontos)
## Uma história ou exemplo para contar em voz
## O que mudou no que eu penso desde que escrevi
## O que aplicar segunda-feira

O de livro tem as ideias principais com o meu comentário, onde eu discordo e para quem recomendo. O de aprendizado tem o contexto, o que eu achava antes e o que faria diferente.

Etapa 3: o roteiro

O roteiro sai de três arquivos juntos: as notas, o guia de voz e o prompt.

O guia de voz é escrito uma vez. Ele diz como eu abro e fecho os episódios, que expressões uso e quais nunca usaria, se explico siglas, e traz trechos dos meus artigos como referência de estilo. Também tem regras fixas: primeira pessoa do singular, nada de exemplos reais do meu time ou da empresa, nada de dados inventados.

A estrutura muda com o tipo de episódio:

Tipo O meio do episódio
Livro Contexto dos autores, de três a cinco ideias-chave com o meu comentário, crítica e aplicação prática
Artigo Por que escrevi, os pontos principais contados como conversa, o que mudou desde então e aplicação prática
Aprendizado O contexto, o que eu achava antes, os aprendizados, o que faria diferente e aplicação prática

Abertura e fechamento são fixos em todos: "Oi, eu sou o Fernando Ghisi, e este é o fghisi podcast" e o convite para as notas no blog.

As regras do prompt existem porque texto para ler e texto para ouvir são coisas diferentes:

  • Frases curtas, sem listas, tabelas ou parênteses.
  • Números por extenso e siglas explicadas na primeira menção.
  • Nunca citar trechos de livros com mais de uma frase: paráfrase e comentário.
  • Nunca inventar o que não está nas notas. Quando faltar um fato, marcar [VERIFICAR]. O pipeline se recusa a gerar o áudio enquanto existir um.
  • Entregar junto o título, a descrição, as notas do episódio com as referências e um rascunho de post para o LinkedIn.

O roteiro pode ser gerado pela API do Claude, num workflow do Actions, com a saída forçada numa ferramenta (tool_choice), para vir sempre estruturado em blocos. Ou pode ser escrito numa conversa e enviado junto com as notas: quando o workflow encontra um roteiro.md pronto, ele não chama a API. Comecei pelo segundo jeito, sem chave da Anthropic.

A revisão é o portão humano. O roteiro chega num pull request, e é ali que se pega erro de fato ou frase que não soa como eu. Na primeira versão, o texto ficou certinho demais e parecia lido. Reescrevi o guia de voz para o tom de um engenheiro conversando com outro, com "pra", "tá", perguntas para quem ouve e exemplos como o PR parado em revisão ou o deploy de sexta-feira.

Etapa 4: a voz

A ElevenLabs gera um pedido por bloco do roteiro, no endpoint POST /v1/text-to-speech/{voice_id}. O corpo de cada pedido fica assim:

{
  "text": "Oi! Eu sou o Fernando Guízi, e este é o f guízi podcast.",
  "model_id": "eleven_multilingual_v2",
  "seed": 42,
  "previous_request_ids": ["…", "…", "…"],
  "voice_settings": {
    "stability": 0.4,
    "similarity_boost": 0.75,
    "style": 0.4,
    "use_speaker_boost": true
  }
}

Cada parâmetro tem um motivo:

  • previous_request_ids encadeia os pedidos, até três anteriores, para a entonação seguir contínua de um bloco para o outro.
  • seed fixo faz uma regeneração sair parecida com a anterior.
  • voice_settings: o padrão da API favorece estabilidade e soa monótono. Estabilidade mais baixa e estilo mais alto deixam a fala mais animada. Os valores ficam em variáveis do repositório, para ajustar sem mexer no código.
  • Pedidos de até 1.500 caracteres: pedidos longos tendem a perder energia no fim.

A pronúncia ganhou um arquivo próprio, porque a voz errava nomes, inclusive o meu. Cada nome é escrito como se lê em português, e a troca vale só para o texto que vai para a voz. A transcrição no site fica com a grafia certa:

{
  "Ghisi": "Guízi",
  "fghisi": "f guízi",
  "Caleb Mellas": "Quêileb Mélas",
  "deploy": "deplói",
  "PR": "pê érre"
}

Antes de começar, o script consulta quantos créditos sobram no mês, quando a chave tem permissão para isso. Se o episódio não couber, ele para sem gastar nada, em vez de ficar pela metade.

Etapa 4, parte 2: a pós-produção

A mixagem: a trilha abre o episódio, abaixa sob a voz e encerra 0 s4 sFIM DA VOZ+10 s vozvozvoz abertura:só a trilha nas pausas, a trilha sobe um pouco encerramento:a trilha sobe e some SOB A VOZ, A TRILHA ABAIXA SOZINHA (SIDECHAIN). O EPISÓDIO FECHA EM -16 LUFS.
A mixagem de cada episódio: a trilha abre, fica baixa sob a voz e encerra.

O primeiro episódio tinha um defeito: o volume caía em alguns trechos. A causa era a normalização numa passada só, que vai mexendo no ganho ao longo do áudio. A pós-produção ficou assim:

  1. Cada parte no mesmo volume. O script mede cada parte que veio da ElevenLabs e aplica o ganho que falta para chegar ao alvo.
  2. Junção, com pausas curtas entre os blocos e mais curtas dentro de um mesmo bloco.
  3. Trilha. Ela abre o episódio sozinha, abaixa quando eu falo e encerra o episódio.
  4. Normalização em duas passadas, para −16 LUFS, o padrão de podcast. A primeira mede, a segunda aplica um ganho único.
  5. Tags ID3: título, autor, a capa e o aviso de que a narração é gerada por IA.
  6. Duração e tamanho em bytes, que o feed RSS exige.

A normalização em duas passadas, no ffmpeg:

# 1ª passada: mede
ffmpeg -i bruto.wav -af loudnorm=I=-16:TP=-1.5:LRA=11:print_format=json -f null -

# 2ª passada: aplica um ganho único com os valores medidos
ffmpeg -i bruto.wav -af loudnorm=I=-16:TP=-1.5:LRA=11:linear=true:measured_I=…:measured_TP=…:measured_LRA=…:measured_thresh=…:offset=… episodio.mp3

A trilha abaixa sob a voz com um filtro de sidechain: a própria voz controla o volume da música.

[música][voz]sidechaincompress=threshold=0.015:ratio=10:attack=60:release=700

Medi o resultado. Com a música por baixo, o volume da fala ficou igual ao da voz sozinha: −16,6 LUFS nos dois casos.

A trilha também é feita por código. É uma faixa original no estilo do pop rock dos anos oitenta: shuffle em meio-tempo, guitarra com chorus no contratempo, uma guitarra solo com vibrato e bends, baixo, bateria e teclados, tudo sintetizado nota a nota em Python. A guitarra usa o algoritmo de Karplus-Strong, que simula uma corda dedilhada com um buffer de ruído que vai sendo suavizado. Como a faixa é minha, não precisei me preocupar com direitos autorais para publicar.

Etapa 5: a publicação

Os MP3 não entram no git. Eles ficam nos releases de um repositório público, separado do site. O repositório do site é privado, e um release privado não abre para os players. O publicar sobe dois arquivos por episódio: o episódio pronto e a voz sozinha, sem trilha.

O site é o próprio blog, gerado pelo Eleventy. Cada episódio é um arquivo Markdown com o endereço do áudio, a duração e o tamanho. Do mesmo build saem:

  • /podcast/, com a capa e a lista de episódios;
  • /podcast/<episódio>/, com o player, as notas e a transcrição completa, que ajuda na busca e na acessibilidade;
  • /podcast/feed.xml, o feed RSS, com as tags de podcast que os aplicativos esperam.

Cada item do feed tem o essencial para os aplicativos:

<item>
  <title>De sênior a principal: o trabalho entre os times</title>
  <enclosure url="https://fghisi.com.br/podcast/audio/2026-10-de-senior-a-principal.mp3"
             length="7532377" type="audio/mpeg"/>
  <itunes:duration>474</itunes:duration>
  <itunes:explicit>false</itunes:explicit>
</item>

Episódio com data futura não gera página nem item no feed até o dia. O deploy roda todo dia de manhã, então dá para agendar.

Por enquanto, o podcast vive só no blog. O feed já está pronto para os aplicativos de podcast, com capa de 3000 × 3000 px e as tags que eles pedem. Levar o podcast até eles é o próximo passo.

A capa, aliás, também sai de um script: as letras da logo do site são convertidas em curvas a partir da fonte, e o resultado vira um PNG de 3000 px.

A orquestração

O plano tinha três workflows. Ficaram dois, mais o deploy que o site já tinha:

Workflow Gatilho O que faz
Roteiro push de notas.md numa branch ep/* Gera o roteiro com o Claude, se ainda não existir, e abre o PR
Áudio label gerar-audio no PR Confere o token, gera a voz, monta o episódio, guarda o MP3 na execução, publica o release, grava a página e comenta o link no PR
Áudio label remixar no PR O mesmo, mas reaproveita a voz já publicada: refaz só a mixagem, sem gastar créditos
Deploy merge na main e todo dia às 6h Gera o site, baixa os MP3 dos releases para dentro dele e publica na Hostinger

Os secrets do repositório são três: a chave da ElevenLabs, o voice_id e um token do GitHub com acesso só ao repositório de áudios. A chave da Anthropic é opcional. As configurações da voz e o modelo ficam em variáveis, que não são secretas.

Os testes cobrem os scripts sem rede, com as APIs simuladas: o front matter, a divisão dos blocos, a pronúncia, a recusa de [VERIFICAR], o encadeamento dos pedidos, os comandos do ffmpeg e a página do episódio. Para o áudio em si, instalei o ffmpeg e testei com vozes do próprio macOS gravadas em volumes diferentes.

O plano e a realidade

Boa parte do desenho original sobreviveu. Mas algumas decisões mudaram no caminho:

No plano Na prática Por quê
Astro Eleventy É o gerador que o site já usa
Cloudflare R2 Releases do GitHub Sem conta nova; o repositório público resolve
Plano Creator e clone profissional Plano Starter e clone rápido Validar tudo antes de pagar mais
Roteiro sempre pela API Roteiro na conversa ou pela API Começar sem mais uma chave
Três workflows Dois, mais o deploy A publicação aproveita o deploy do site
MP3 tocado direto do GitHub MP3 servido pelo site O Safari do iPhone não tocava
Só voz Voz com trilha Deixou o episódio com cara de podcast

O que deu errado

Vale contar, porque foi onde eu mais aprendi.

O token errado custou três vozes. O token que publica no repositório de áudios apontava para o repositório errado. A voz era gerada, a publicação falhava, e o áudio se perdia junto com a máquina do Actions. Três vezes, e cada tentativa gastou créditos. A correção é a de qualquer sistema: falhar cedo. Agora o workflow confere a permissão antes de gerar a voz, criando o release como rascunho, e guarda o MP3 na execução assim que ele fica pronto.

A correção não valeu na hora. O evento de pull request roda o workflow da junção da branch com a base, e essa junção não foi atualizada quando a correção entrou na develop. Uma tentativa ainda rodou com a versão antiga. Lição: atualizar a branch do episódio antes de tentar de novo.

O Actions não podia abrir pull request. A configuração do repositório não deixa, e o workflow do roteiro falhava no último passo. Agora ele só avisa, e o PR é aberto à mão.

O Safari do iPhone não tocava. O GitHub entrega o arquivo do release como download, com Content-Type: application/octet-stream, e o Safari do iOS se recusa a tocar assim dentro da página. A solução foi servir o MP3 pelo próprio site: no deploy, o pipeline baixa cada áudio para dentro dele.

A voz soou robotizada. Boa parte veio do roteiro certinho e das configurações padrão, e foi resolvida. O resto é o limite do clone rápido, que copia o timbre mas não o meu jeito de falar.

Quanto custa

Item Custo
ElevenLabs, plano Starter cerca de US$ 5 por mês, com créditos para uns dois episódios
ElevenLabs, plano Creator (se crescer) cerca de US$ 22 por mês, com o clone profissional
Roteiro com o Claude centavos por episódio pela API, ou nada, se escrito na conversa
GitHub, Actions e releases US$ 0
Hospedagem e domínio já pagos pelo site

Os cuidados

  • Direito autoral. A Lei 9.610/98, no artigo 46, inciso III, permite citar trechos para crítica ou estudo, na medida justificada e indicando autor e obra. Por isso o prompt proíbe citações longas e pede paráfrase e comentário. Não sou advogado; em caso de dúvida, vale consultar um.
  • Transparência. A página do podcast, cada episódio e as tags do MP3 dizem que a narração é gerada por IA a partir da minha voz. O primeiro episódio abre explicando isso.
  • Segurança da voz. A chave da ElevenLabs fica só nos secrets, o token do GitHub só enxerga o repositório de áudios, e o voice_id não aparece em lugar público. A verificação em duas etapas na conta da ElevenLabs é o próximo passo.
  • Empresa. A mesma regra dos artigos: nada de exemplos do meu time ou da empresa em que eu trabalho.

O que eu levo disso

O podcast confirmou uma coisa que eu já via no amardoar: a IA acelera muito, mas o que dá segurança é o processo. Branch, pull request, revisão, testes e deploy automático. O mesmo ciclo que a gente roda nos times.

E confirmou outra: o erro mais caro é o que aparece no fim. Mover as verificações para o começo do pipeline, antes da etapa que gasta dinheiro, é a primeira melhoria que eu faria em qualquer automação parecida.

O primeiro episódio está no ar. Se você ouvir, me conta o que achou.

Fontes