Communitygithub.com

adao-max/agent-skills

Desenhe animações com código Manim, adicione narração em chinês e crie vídeos explicativos no estilo 3Blue1Brown, de 1 a 5 minutos, entregando MP4 em 1080p.

O que é agent-skills?

Esta skill permite que um agente de IA crie vídeos explicativos animados no estilo 3Blue1Brown usando Manim, com narração em chinês. O processo começa com a escrita de um roteiro seguindo a estrutura 'problema → exemplo concreto → variação → regra geral → novo exemplo → resposta', dividido em 5 a 10 segmentos. A narração é definida em um arquivo `narration.json`, com suporte a leitura diferenciada (texto na tela vs. pronúncia para TTS). A skill automatiza a geração de áudio (via MiniMax), a renderização das animações (Manim), a criação de contact sheets para revisão visual e a verificação final (incluindo sincronia de legendas e áudio). Suporta plataformas como Claude Code, Cursor e Codex, e foi projetada para macOS e Linux, com scripts auxiliares disponíveis em `scripts/`. O resultado é um vídeo 1080p/30fps com legendas sincronizadas, cores consistentes e layout otimizado para evitar sobreposição.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/adao-max/agent-skills/tree/HEAD/skills/explainer-video

Perguntar na sua IA favorita

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

Documentação

Vídeo Explicativo Programático

Ambiente

  • Instale o Manim: uv tool install manim. Se houver erro sobre pycairo não encontrar pkg-config, execute brew install pkgconf.
  • Use a ferramenta de linha de comando mmx do MiniMax para narração e transcrição. Instalação: npm install -g mmx-cli, depois faça login com mmx auth login --api-key <sua chave de API MiniMax>. Se mmx reportar não autenticado ou saldo insuficiente, pare e avise o usuário.
  • contact_sheet.py usa o Pillow do Python do sistema, além de ffmpeg e ffprobe (brew install ffmpeg).
  • macOS usa PingFang SC por padrão. No Linux, instale fontes chinesas, por exemplo fonts-noto-cjk no Debian/Ubuntu. A classe base verifica se a fonte existe e para se estiver ausente. Para fontes personalizadas, use EXPLAINER_CN_FONT e EXPLAINER_EN_FONT; a fonte deve suportar todos os caracteres do texto. Em outros sistemas, instale Manim, Pillow e FFmpeg com o gerenciador de pacotes correspondente.
  • A maioria dos exemplos de 3Blue1Brown online usa manimlib, cuja API difere do Manim Community — não copie diretamente.
  • scripts/ desta skill:
    • gen_audio.py: Gera narração e timestamps palavra por palavra.
    • explainer_base.py: Classe base de cena, divisão de legendas, temporização, layout e limpeza.
    • contact_sheet.py: Extrai frames por nó de animação e máxima duração de legenda, priorizando verificação de layout com duas linhas.
    • verify_video.py: Verifica glifos das legendas, tempos de narração e resultados de decodificação no vídeo final.
    • test_subtitles.py: Usa renderização real do Manim para reproduzir bugs antigos e verificar regressões de legendas.

Fluxo

Coloque o diretório do projeto em ~/video-studio/explainers/<tema>/.

  1. Escreva um esboço. Siga a ordem "apresentar problema → exemplo concreto → como o exemplo varia → regra geral → testar com novo exemplo → responder à pergunta inicial", dividindo em 5 a 10 segmentos, cada um com apenas um ponto. Se a duração total exceder 3 minutos, envie o esboço para o usuário confirmar.
  2. Escreva narration.json. As chaves são nomes de segmento (s1, s2...), e os valores são a narração. Escreva a narração em linguagem coloquial, frases curtas, cada frase tratando apenas de uma coisa. Se a skill chinese-writing-style estiver instalada, siga-a; cada segmento deve ter 3 a 6 frases. Se o TTS puder ler incorretamente uma palavra ou sigla em inglês, use {"text": "texto na tela e alinhamento", "tts": "leitura para o TTS"}.
  3. Execute python3 <skill>/scripts/gen_audio.py <diretório do projeto>. O timbre padrão da narração é Chinese (Mandarin)_Warm_Girl. Anos, datas e outros números devem ser escritos em leitura chinesa no campo tts; o campo text mantém os algarismos arábicos na tela. Para refazer apenas alguns segmentos, adicione --only s3,s5. Se a saída for "transcrição e narração divergentes", verifique se o TTS leu errado uma palavra-chave. Se estiver errada, corrija o tts daquele segmento e refaça com --only. Se faltarem timestamps palavra por palavra, primeiro complete a transcrição; não estime legendas com base na proporção de caracteres do segmento inteiro.
  4. Use um link simbólico para incluir o scripts/explainer_base.py compartilhado e escreva scene.py. Em projetos existentes, remova implementações locais de legendas e sobrescritas de start/finish, mantenha a lógica visual, faça backup da classe base antiga e substitua pelo link. O projeto deve desenhar apenas as cenas explicativas; as legendas são geradas uniformemente pela classe base.
  5. No diretório do projeto, execute manim -ql --disable_caching scene.py <NomeDaClasse>. Se houver erro "animação não acompanha narração", encurte o run_time da animação correspondente ou remova a animação, e renderize novamente.
  6. Execute python3 <skill>/scripts/contact_sheet.py <vídeo de visualização> <diretório do projeto> e examine cada mosaico. Verifique layout das legendas, sobreposição de elementos e direção das setas. Para frases animadas com tempo estimado, confira com os timestamps das palavras em audio/<segmento>.words.json.
  7. Execute manim --resolution 1920,1080 --frame_rate 30 --disable_caching scene.py <NomeDaClasse>. Não use -qh (60 fps). Use o Python que instalou o Manim para executar <skill>/scripts/verify_video.py <vídeo final> <diretório do projeto>. O interpretador correspondente a uv tool install manim é $(uv tool dir)/manim/bin/python.
  8. O comando de verificação deve ter código de saída 0 e o campo passed de qa/video-check.json deve ser true. Se houver falha em glifos, tempo de áudio ou posicionamento de legendas, examine o relatório, capturas de tela e o words.json correspondente; corrija e renderize/verifique novamente. Legendas estimadas não podem ser aprovadas apenas com capturas de tela.
  9. Após aprovação, copie como <tema>-explicação.mp4, informe o caminho do vídeo ao usuário e, se o ambiente atual permitir enviar arquivos, envie diretamente. Remova as prévias de baixa resolução em media/.

Código da Cena

from explainer_base import *

class Topico(CenaExplicativa):
    def s1(self):
        self.start("s1")              # Toca a narração e exibe legendas sincronizadas automaticamente
        titulo = cn("Taxa de Aprendizado", 60, HI)
        self.play(Write(titulo))
        self.until("taxa de aprendizado muito pequena")  # Aguarda até que a narração leia esta frase
        self.play(titulo.animate.to_edge(UP))
        self.finish()                 # Aguarda o fim da narração, limpa legendas e desvanece a cena
  • Cada segmento tem um método com o mesmo nome.
  • Não sobrescreva start, finish ou o updater de legendas no projeto. Se o usuário explicitamente não quiser legendas, defina o atributo de classe SUBTITLES = False.
  • Para trocar de cena dentro de um segmento, apenas desvaneça ou remova os objetos que você criou, mantendo as legendas da classe base. Não limpe self.mobjects inteiro nem chame self.clear().
  • A frase em until deve aparecer exatamente no text da narração daquele segmento e ocorrer apenas uma vez.
  • Use cn() para chinês e en() para inglês. O tamanho da fonte não deve ser inferior a 22.
  • Use apenas as 4 cores da classe base: MAIN (corpo), HI (destaque), OK (correto), BAD (erro). Cada cor deve ter o mesmo significado em todo o vídeo.
  • Máximo de 3 grupos de elementos por tela. Antes de trazer novo conteúdo, desvaneça o que não será mais falado.
  • Reserve os 20% inferiores da tela para legendas; gráficos e textos explicativos devem ficar acima dessa área.
  • O elemento que está sendo narrado deve aparecer, mudar de cor ou se mover.

Armadilhas Comuns

  • Após modificar o código compartilhado de legendas, execute test_subtitles.py com o Python que instalou o Manim. Ele deve passar nas verificações de espera real, alternância entre segmentos, legendas de duas linhas, frases curtas repetidas, paginação de frases longas e alinhamento de diferentes leituras. Apenas modificar manualmente renderer.time e chamar o updater não valida o comportamento de espera estática do Manim.
  • Text não quebra linha automaticamente; use \n para frases longas.
  • Para textos dentro de molduras, use fit(texto, largura_moldura * 0.8) para limitar a largura.
  • Ao usar Cross para riscar uma opção, risque apenas o texto, não as setas; mude a cor das setas para BAD.
  • Para colorir palavras dentro de uma frase, use Text(..., t2c={"palavra": cor}).

Habilidades Relacionadas