Transcrição do YouTube
Baixa transcrições (legendas/closed captions) de vídeos do YouTube. Funciona tanto com transcrições criadas manualmente quanto com as geradas automaticamente. Não requer chave de API ou navegador — usa a API InnerTube do YouTube diretamente e recorre automaticamente ao yt-dlp quando o YouTube bloqueia o caminho direto da API.
Busca metadados do vídeo e imagem de capa na primeira execução, armazena em cache os dados brutos para uma reformatação rápida.
Diretório do Script
Scripts no subdiretório scripts/. {baseDir} = caminho do diretório deste SKILL.md. Resolver o runtime ${BUN_X}: se bun estiver instalado → bun; se npx estiver disponível → npx -y bun; caso contrário, sugerir a instalação do bun. Substituir {baseDir} e ${BUN_X} pelos valores reais.
| Script | Finalidade |
|---|---|
scripts/main.ts | CLI para download de transcrição |
Uso
# Padrão: markdown com carimbos de tempo (Inglês)
${BUN_X} {baseDir}/scripts/main.ts <youtube-url-or-id>
# Especificar idiomas (ordem de prioridade)
${BUN_X} {baseDir}/scripts/main.ts <url> --languages zh,en,ja
# Sem carimbos de tempo
${BUN_X} {baseDir}/scripts/main.ts <url> --no-timestamps
# Com segmentação por capítulos
${BUN_X} {baseDir}/scripts/main.ts <url> --chapters
# Com identificação de locutores (requer pós-processamento com IA)
${BUN_X} {baseDir}/scripts/main.ts <url> --speakers
# Arquivo de legenda SRT
${BUN_X} {baseDir}/scripts/main.ts <url> --format srt
# Traduzir transcrição
${BUN_X} {baseDir}/scripts/main.ts <url> --translate zh-Hans
# Listar transcrições disponíveis
${BUN_X} {baseDir}/scripts/main.ts <url> --list
# Forçar nova busca (ignorar cache)
${BUN_X} {baseDir}/scripts/main.ts <url> --refresh
Opções
| Opção | Descrição | Padrão |
|---|---|---|
<url-or-id> | URL do YouTube ou ID do vídeo (vários permitidos) | Obrigatório |
--languages <codes> | Códigos de idioma, separados por vírgula, em ordem de prioridade | en |
--format <fmt> | Formato de saída: text, srt | text |
--translate <code> | Traduzir para o código de idioma especificado | |
--list | Listar transcrições disponíveis em vez de buscar | |
--timestamps | Incluir carimbos de tempo [HH:MM:SS → HH:MM:SS] por parágrafo | ativado |
--no-timestamps | Desativar carimbos de tempo | |
--chapters | Segmentação por capítulos a partir da descrição do vídeo | |
--speakers | Transcrição bruta com metadados para identificação de locutores | |
--exclude-generated | Pular transcrições geradas automaticamente | |
--exclude-manually-created | Pular transcrições criadas manualmente | |
--refresh | Forçar nova busca, ignorar dados em cache | |
-o, --output <path> | Salvar em caminho de arquivo específico | gerado automaticamente |
--output-dir <dir> | Diretório de saída base | youtube-transcript |
Variáveis de Ambiente Opcionais
| Variável | Descrição |
|---|---|
YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER | Passado para yt-dlp --cookies-from-browser durante o fallback, ex: chrome, safari, firefox, ou chrome:Profile 1 |
Formatos de Entrada
Aceita qualquer um destes como entrada de vídeo:
- URL completa:
https://www.youtube.com/watch?v=dQw4w9WgXcQ - URL curta:
https://youtu.be/dQw4w9WgXcQ - URL de incorporação:
https://www.youtube.com/embed/dQw4w9WgXcQ - URL do Shorts:
https://www.youtube.com/shorts/dQw4w9WgXcQ - ID do vídeo:
dQw4w9WgXcQ
Formatos de Saída
| Formato | Extensão | Descrição |
|---|---|---|
text | .md | Markdown com frontmatter (incl. description), cabeçalho de título, resumo, TOC/capa/carimbos de tempo/capítulos/locutores opcionais |
srt | .srt | Formato de legenda SubRip para players de vídeo |
Diretório de Saída
youtube-transcript/
├── .index.json # Mapeamento ID do vídeo → caminho do diretório (para consulta de cache)
└── {channel-slug}/{title-full-slug}/
├── meta.json # Metadados do vídeo (título, canal, descrição, duração, capítulos, etc.)
├── transcript-raw.json # Trechos brutos da transcrição da API do YouTube (em cache)
├── transcript-sentences.json # Transcrição segmentada por frases (dividida por pontuação, mesclada entre trechos)
├── imgs/
│ └── cover.jpg # Miniatura do vídeo
├── transcript.md # Transcrição em Markdown (gerada a partir das frases)
└── transcript.srt # Legenda SRT (gerada a partir dos trechos brutos, se --format srt)
{channel-slug}: Nome do canal em kebab-case{title-full-slug}: Título completo do vídeo em kebab-case
O modo --list gera saída apenas para stdout (nenhum arquivo é salvo).
Cache
Na primeira execução, o script salva:
meta.json— metadados do vídeo, capítulos, caminho da imagem de capa, informações de idiomatranscript-raw.json— trechos brutos da transcrição da API do YouTube ({ text, start, duration }[])transcript-sentences.json— transcrição segmentada por frases ({ text, start: "HH:mm:ss", end: "HH:mm:ss" }[]), dividida por pontuação de final de frase (.?!…。?!etc.), carimbos de tempo alocados proporcionalmente pelo comprimento dos caracteres, mesclagem de texto com reconhecimento CJKimgs/cover.jpg— miniatura do vídeo
Execuções subsequentes para o mesmo vídeo usam dados em cache (sem chamadas de rede). Use --refresh para forçar uma nova busca. Se um idioma diferente for solicitado, o cache é automaticamente atualizado.
Quando o YouTube retorna respostas anti-bot / bloqueadas no caminho direto do InnerTube, o script tenta novamente com identidades de cliente alternativas e depois recorre ao yt-dlp se disponível. Se o fallback for necessário, mas o yt-dlp não estiver disponível, o agente deve decidir como disponibilizar o yt-dlp e continuar, em vez de empurrar a decisão de instalação para o usuário.
A saída SRT (--format srt) é gerada a partir de transcript-raw.json. A saída de texto/markdown usa transcript-sentences.json para limites naturais de frases.
Fluxo de Trabalho
Quando o usuário fornece uma URL do YouTube e deseja a transcrição:
- Execute com
--listprimeiro se o usuário não especificou um idioma, para mostrar as opções disponíveis - Sempre coloque a URL entre aspas simples ao executar o script — o zsh trata
?como um curinga glob, então uma URL do YouTube sem aspas causa "no matches found": use'https://www.youtube.com/watch?v=ID' - Padrão: execute com
--chapters --speakerspara a saída mais completa (capítulos + identificação de locutores) - O script salva automaticamente os dados em cache + arquivo de saída e imprime o caminho do arquivo
- Para o modo
--speakers: depois que o script salva o arquivo bruto, siga o fluxo de trabalho de identificação de locutores abaixo para pós-processar com rótulos de locutores
Quando o usuário deseja apenas uma imagem de capa ou metadados, executar o script com qualquer opção também colocará em cache meta.json e imgs/cover.jpg.
Ao reformatar o mesmo vídeo (ex: primeiro texto depois SRT), os dados em cache são reutilizados — não é necessário buscar novamente.
Fluxo de Trabalho de Capítulos e Locutores
Capítulos (--chapters)
O script analisa os carimbos de tempo dos capítulos a partir da descrição do vídeo (ex: 0:00 Introdução), segmenta a transcrição pelos limites dos capítulos, agrupa os trechos em parágrafos legíveis e salva como .md com um Índice. Nenhum processamento adicional é necessário.
Se não existirem carimbos de tempo de capítulos na descrição, a transcrição é gerada como parágrafos agrupados sem cabeçalhos de capítulo.
Identificação de Locutores (--speakers)
A identificação de locutores requer processamento de IA. O script gera um arquivo .md bruto contendo:
- Frontmatter YAML com metadados do vídeo (título, canal, data, capa, descrição, idioma)
- Descrição do vídeo (para extração de nomes dos locutores)
- Lista de capítulos da descrição (se disponível)
- Transcrição bruta em formato SRT (carimbos de tempo de início/fim pré-computados, eficiente em tokens)
Depois que o script salva o arquivo bruto, inicie um subagente (use um modelo mais barato como o Sonnet para eficiência de custos) para processar a identificação de locutores:
- Leia o arquivo
.mdsalvo - Leia o modelo de prompt em
{baseDir}/prompts/speaker-transcript.md - Processe a transcrição bruta seguindo o prompt:
- Identifique os locutores usando os metadados do vídeo (título → convidado, canal → apresentador, descrição → nomes)
- Detecte mudanças de locutor a partir do fluxo da conversa, padrões de pergunta-resposta e pistas contextuais
- Segmente em capítulos (use os capítulos da descrição se disponíveis, caso contrário crie a partir de mudanças de tópico)
- Formate com rótulos
**Nome do Locutor:**, agrupamento de parágrafos (2-4 frases) e carimbos de tempo[HH:MM:SS → HH:MM:SS]
- Sobrescreva o arquivo
.mdcom a transcrição processada (mantenha o frontmatter YAML)
Quando --speakers é usado, --chapters está implícito — a saída processada sempre inclui segmentação por capítulos.
Casos de Erro
| Erro | Significado |
|---|---|
| Transcrições desativadas | O vídeo não possui legendas |
| Nenhuma transcrição encontrada | O idioma solicitado não está disponível |
| Vídeo indisponível | Vídeo excluído, privado ou com restrição regional |
| IP bloqueado | Muitas solicitações, tente novamente mais tarde |
| Restrição de idade | O vídeo requer login para verificação de idade |
| bot detectado | O script tenta novamente com clientes alternativos e depois yt-dlp; se a ferramenta de fallback estiver ausente, o agente deve resolver isso por conta própria, caso contrário, se ainda falhar, tente YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER=safari (ou seu navegador) |


