Executando verificação de segurança...
2

Pitch: Transformando vídeos do Youtube e X/Twitter de horas em artigos que dá pra ler

Disclaimer: construí este projeto para testar conceitos e técnicas de desenvolvimento com o Claude Code e aplicar na prática os conhecimentos que venho adquirindo. É um laboratório pessoal que acabou virando algo útil pra mim, e documento aqui para quem estiver interessado em como um pipeline assim se monta na prática.

Vídeo longo é um formato hostil pra quase tudo que não seja assistir do começo ao fim, sentado. Um podcast de 2, 3, 4 horas no YouTube é díficil de ser consumido até para assuntos interessantes.

Vídeo é pior ainda pra:

  • Pesquisar: Ctrl+F não existe. Achar "o trecho onde o fulano falou sobre X" requer navegar timestamps manualmente.
  • Citar: link com timestamp resolve mal, e transcrever é trabalhoso.
  • Reler: não tem marcador visual, não tem progresso, não tem seções nomeadas.
  • Skim: não dá pra bater o olho e decidir se vale o investimento de tempo.

Artigo resolve tudo isso. Mas quase nenhum podcast tem versão escrita decente, e legendas automáticas do YouTube são ilegíveis — paredão de texto sem pontuação, cheio de "é, tipo, né, então".

O objetivo do projeto

Vídeo to text é transformar vídeos do YouTube ou Twitter/X em artigos organizados por seções temáticas.

Cada artigo tem:

  • Título e subtítulo limpos
  • Índice clicável
  • Seções temáticas (não cronológicas — reorganizadas por assunto)
  • Barra de progresso de leitura
  • "Continuar de onde parou" salvo por dispositivo
  • Sidebar de referências: livros citados linkados no Amazon, ferramentas com site oficial, pessoas com Twitter, conceitos com Wikipedia, posts relacionados
  • Switcher de idioma PT/EN no header

Zero framework. HTML estático servido no GitHub Pages. Carrega rápido em qualquer coisa, inclusive 3G sofrido.

A pipeline

URL do vídeo (YouTube ou Twitter/X)
  ↓
Detecta provider pela URL
  ↓
YouTube: youtube-transcript-api (legendas oficiais quando existem)
Twitter/X: yt-dlp baixa áudio → mlx-whisper transcreve local
  ↓
Transcrição bruta em inglês (ou idioma original do vídeo)
  ↓
Claude (organização): lê transcrição, remove "né", "tipo", timestamps,
                      sponsor reads, reorganiza em seções temáticas,
                      produz texto natural em PT-BR e em EN
  ↓
Python gera HTML com JSON-LD, Open Graph, hreflang, sidebar de referências
  ↓
Git commit + push → GitHub Pages publica

Sem CMS, sem banco de dados, sem etapa de build em frontend. O script src/build_html.py tem ~400 linhas de Python puro e escreve HTML semântico direto:

return f'''<!DOCTYPE html>
<html lang="{html_lang}">
<head>
<link rel="alternate" hreflang="pt-BR" href="{pt_href}">
<link rel="alternate" hreflang="en" href="{en_href}">
<script type="application/ld+json">{jsonld}</script>
<link rel="stylesheet" href="../../css/style.css">
</head>
<body class="page-article">
<header class="site-header">...</header>
<article class="container">
  <h1>{title}</h1>
  <nav><h3>Conteúdo</h3><ol>{toc_html}</ol></nav>
  {body_html}
</article>
{references_sidebar}
</body>
</html>'''

O Whisper local

Pra vídeos do Twitter/X (ou YouTube quando a legenda oficial está bloqueada) o pipeline usa mlx-whisper — a implementação MLX do Whisper, otimizada nativa pro Apple Silicon. Custo de transcrição: zero. Velocidade: ~5× real-time num M1 Pro. Um podcast de 1 hora transcreve em uns 12 minutos.

import mlx_whisper

result = mlx_whisper.transcribe(
    audio_path,
    path_or_hf_repo="mlx-community/whisper-large-v3-turbo",
    word_timestamps=False,
)

Em Linux ou Windows dá pra trocar por faster-whisper (CTranslate2), mesma ideia. O importante é não mandar áudio pra API de ninguém — Whisper rodando local é bom o suficiente e é grátis.

Markdown para agentes

A Cloudflare tem uma feature chamada Markdown for Agents que converte HTML em Markdown na edge quando um agente de IA faz a requisição com Accept: text/markdown. Essa feature só existe no plano pago (Pro ou Business).

Dá pra replicar em ~150 linhas de JavaScript rodando no plano Free (100k requests/dia) do Cloudflare Workers. HTMLs bem estruturados não precisam de nada muito sofisticado — regex resolve:

export default {
  async fetch(request) {
    const accept = request.headers.get("Accept") || "";
    if (!accept.includes("text/markdown")) {
      return fetch(request); // passa HTML direto pra humanos
    }

    // Agente pediu markdown. Busca HTML do origin e converte.
    const response = await fetch(new Request(request.url, {
      headers: { Accept: "text/html" }
    }));
    const html = await response.text();

    const articleHtml = html.match(/<article[^>]*>([\s\S]*?)<\/article>/i)?.[1];
    const markdown = htmlToMarkdown(articleHtml);

    return new Response(frontmatter + markdown, {
      headers: {
        "Content-Type": "text/markdown; charset=utf-8",
        "x-markdown-tokens": String(Math.ceil(markdown.length / 4)),
        "Vary": "Accept",
      }
    });
  }
};

Resultado: um HTML de artigo que custa ~53.000 tokens pra um agente parsear vira ~13.000 tokens em Markdown — redução de 75%. Sem Turndown, sem JSDOM (nenhum dos dois roda em Worker runtime), só regex e uns cuidados com <pre> e <code>.

Dá pra testar:

# Humano recebe HTML
curl -sI https://adhenawer.net/posts/original/state-ai-2026.html | grep -i content-type
# content-type: text/html; charset=utf-8

# Agente recebe Markdown
curl -s https://adhenawer.net/posts/original/state-ai-2026.html \
  -H "Accept: text/markdown" | head -10
# ---
# title: "The State of AI in 2026"
# lang: en
# ---
# ## THE NOVEMBER INFLECTION POINT
# ...

Referências extraídas automaticamente

Cada artigo tem uma sidebar fixa com referências extraídas da transcrição. Categorias:

  • Livros → busca no Amazon
  • Ferramentas → site oficial
  • Papers → arXiv ou blog do autor
  • Pessoas → Twitter/X (prioridade), fallback pra Wikipedia
  • Conceitos → Wikipedia
  • Empresas → site oficial
  • Posts relacionados → cross-link interno pro mesmo tema em outros artigos

A extração é feita por subagentes do Claude em paralelo — um por artigo, cada um recebe a transcrição e devolve um JSON estruturado:

{
  "video_id": "...",
  "books": [
    {
      "title": "Functional Programming in Scala",
      "author": "Paul Chiusano & Rúnar Bjarnason",
      "url": "https://www.amazon.com/s?k=functional+programming+in+scala+chiusano",
      "context": "..."
    }
  ],
  "people": [
    {
      "name": "Boris Cherny",
      "role": {"pt": "Chefe do Claude Code, Anthropic", "en": "Head of Claude Code, Anthropic"},
      "url": "https://twitter.com/bcherny"
    }
  ],
  "related_posts": [
    {
      "slug_pt": "...",
      "slug_en": "...",
      "reason": {"pt": "...", "en": "..."}
    }
  ]
}

Fluxo dentro do Claude Code

O projeto roda dentro do Claude Code (a CLI oficial da Anthropic). No terminal, dentro do repo:

> adiciona artigo de https://youtu.be/VIDEO_ID

O agente executa o pipeline sozinho: busca transcrição, organiza em seções, traduz pra PT-BR, gera o HTML, atualiza o docs/index.html, atualiza o sitemap.xml, extrai referências, commita e faz push. Revisão do diff fica por conta do humano.

Isso funciona por dois motivos:

  • CLAUDE.md: um arquivo markdown na raiz que contém a base de conhecimento do projeto (convenções, estrutura de pastas, formato de slug). Funciona como memória persistente entre sessões.
  • Subagentes para paralelismo: tarefas que podem ser quebradas em unidades independentes (como extrair referências de N artigos) rodam em subagentes paralelos com contexto isolado. Main context não é poluído.

Stack completo

CamadaTecnologia
InterfaceClaude Code (CLI)
ModeloClaude Opus 4.6 (plano Max da Anthropic)
Transcrição YouTubeyoutube-transcript-api
Transcrição Twitter/Xyt-dlp + mlx-whisper
Organização/traduçãoClaude
Build HTMLPython puro (~400 linhas)
FrontendHTML estático, CSS em um arquivo
HostingGitHub Pages
Domínio + CDNCloudflare (Free)
Edge / agentesCloudflare Worker (Free) — Markdown on demand
AnalyticsUmami Cloud (Free tier)

Infraestrutura sem custo mensal. O único gasto recorrente é a assinatura Claude Max, que já uso para outras coisas — o projeto é um consumidor a mais dessa cota.

O que tem de aberto

Código todo em github.com/adhenawer/video-to-text:

  • src/pipeline.py — orquestrador de ponta a ponta
  • src/providers/ — abstração multi-provider (YouTube, Twitter/X). Adicionar um novo provider (Vimeo, TikTok) exige implementar detect(url), extract_id(url) e fetch_transcript(url).
  • src/build_html.py — geração de HTML
  • workers/markdown-agent/src/index.js — Worker do Cloudflare
  • transcripts/ — transcrições originais + traduzidas + JSONs de referências

Artigos

O índice completo de artigos está em adhenawer.net (PT-BR) e adhenawer.net/en/ (inglês).

Carregando publicação patrocinada...