Communitygithub.com

localizing-video

Faça um vídeo em língua estrangeira virar inglês — dublagem síncrona + legendas + tradução de texto na tela, 100% local/grátis no Apple Silicon.

O que é localizing-video?

Este skill permite que um agente de IA transforme vídeos em línguas estrangeiras (especialmente mandarim/japonês do YouTube, com narração + slides) em versões totalmente em inglês, com dublagem neural síncrona, legendas queimadas e tradução de texto na tela — tudo localmente, sem APIs pagas, no Apple Silicon. A implementação de referência em `engine/` fornece um pipeline completo e testado (yt-dlp, Whisper, Kokoro-onnx TTS, ffmpeg/libass, OCR com ocrmac) que evita as armadilhas comuns — como o acúmulo de drift na dublagem, fontes gigantes das legendas, quebra do espeak-ng e a verificação silenciosa de legendas nativas do YouTube (que podem tornar o pipeline desnecessário). O agente é instruído a não reimplementar do zero, mas sim adaptar o motor existente, traduzindo ele mesmo o roteiro (com foco em trans-criação de piadas e preservação de tom) e usando o OCR para capturar trocadilhos homofônicos que o ASR perde. A habilidade também introduz o conceito de 'time-density' — retemporizar a linha do tempo visual (congelando slides estáticos) para dar espaço à dublagem mais lenta do inglês, sem necessidade de compressão agressiva. Plataformas: macOS/Apple Silicon. Compõe com o skill `hardsubbing-video` para a queima de legendas com ffmpeg/libass.

Funciona com~Claude Code✓Codex CLI✓Cursor✓Antigravity
npx skills add evnchn-agentic/localizing-video

Perguntar na sua IA favorita

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

Documentação

O que localizing-video faz?

Transforme um vídeo em língua estrangeira em inglês — dublagem sincronizada + legendas em inglês + texto na tela traduzido — 100% local/grátis no Apple Silicon. Um agente capaz rederivará a canalização (yt-dlp, whisper, ffmpeg, scene-detect, mux); este skill existe para as escolhas de ferramentas e footguns silenciosos que a rederivação erra, e para a implementação de referência comprovada.

Implementação de referência (comece aqui)

Este repositório entrega o pipeline funcional: engine/ é o motor genérico e executável (build_dub.py — ancorado por bloco, sem drift (veja o footgun da dublagem), make_ass.py, dense_ocr.py, dedup_spans.py, render_overlay.py, run.sh); example/ é um conjunto de dados completo e trabalhado. Leia engine/SETUP.md + example/README.md e execute o motor — não escreva do zero. Por vídeo, o único trabalho novo é produzir en.srt + translations.json (a etapa de tradução). O motor assume uma fonte 1920×1080.

Pipeline + a decisão em cada etapa

  1. Download yt-dlp (tente --extractor-args "youtube:player_client=web_safari,ios,tv" em 403; o formato HLS frequentemente funciona quando o DASH está com DRM).
  2. ASR — mas yt-dlp --list-subs PRIMEIRO (veja footgun): uma faixa manual/criador pode vencer o Whisper de graça, a tag -orig revela o verdadeiro idioma de origem (evita que você use o Whisper por 16 min para nada se o vídeo já estiver no idioma alvo), e uma legenda automática -orig é um segundo ASR gratuito para verificação cruzada. Depois, openai-whisper whisper source.mp4 --model large-v3-turbo --language <zh/ja> --word_timestamps True --output_format all (mantenha o JSON). Fixe o idioma. (torch não tem wheel para py3.14 → execute o whisper a partir de um venv py3.12.)
  3. Traduza a transcrição VOCÊ MESMO (o agente, em-loop) — grátis, com noção de tom, consistência de jargão. Mantenha o mapeamento 1:1 segmento↔timestamp. Corrija nomes próprios com conhecimento (o ASR os ouve errado). Preserve a piada, não apenas as palavras — trocadilhos raramente sobrevivem à tradução literal; trans-crie um trocadilho em inglês que carregue o mesmo mecanismo, e entregue a conclusão na legenda (portadora principal da piada — a dublagem passa por cima do original com volume reduzido). Trocadilhos homofônicos são invisíveis no ASR (veja footgun), então faça OCR da legenda para encontrá-los.
  4. Dublagem — Kokoro-onnx TTS (veja footguns). Síntese por bloco de frase, ancore cada bloco ao seu timestamp verdadeiro (NÃO persiga o drift por segmento — ele acumula atraso), ajuste de tempo, mix. Retemporize os visuais para encontrar a dublagem, não apenas a dublagem para o relógio — veja Time-density.
  5. Legendas — queime o inglês em uma barra letterbox, NÃO sobre o quadro (veja footguns).
  6. OCR visual — ocrmac (Apple Vision), denso a 1fps, deduplicado em intervalos de tempo.
  7. Traduza as strings visuais VOCÊ MESMO; sobreponha o inglês sobre as caixas apenas em chinês.
  8. Mux — ffmpeg-full (libass), overlay → letterbox → queima de legenda → áudio da dublagem.

Footguns — a razão real deste skill existir

ArmadilhaRealidade / correção
ffmpeg não tem filtro subtitlesO ffmpeg padrão do brew não tem libass. Use /opt/homebrew/opt/ffmpeg-full/bin/ffmpeg. (skill: hardsubbing-video)
TTS = say é monótono/robóticoPadrão: Kokoro-onnx (grátis, neural, compatível com py3.14 via onnxruntime). Voz masculina am_michael/etc.
Kokoro falha silenciosamente: phontab ... No such fileO caminho dos dados do espeak-ng está quebrado. brew install espeak-ng, depois no script sobrescreva espeakng_loader.get_data_path/get_library_path → /opt/homebrew/share/espeak-ng-data + /opt/homebrew/lib/libespeak-ng.dylib.
Inglês é mais denso de dizer do que ZH/JA → dublagem atrasaNÃO use atempo (>1,25× = artefatos de vocoder) — re-sintetize na velocidade nativa do Kokoro. NÃO persiga drift com um cursor contínuo (cursor-start catch-up): empiricamente ele acumula ~+5s no meio do vídeo em fala densa consecutiva. Em vez disso: (a) ancore cada enunciado ao seu início verdadeiro (= a linha do tempo da legenda/vídeo) para que o drift não possa acumular; (b) agrupe segmentos ASR adjacentes em enunciados do tamanho de frases para que uma linha longa em inglês pegue tempo emprestado de um vizinho curto — o ajuste por segmento truncou 59% das linhas em um limite de 1,9×; o agrupamento em frases reduziu isso para ~0. Ancorar mata o drift, NÃO a ultrapassagem — um bloco cujo áudio excede seu intervalo ainda colide com o próximo ponto de ancoragem. Ordem de fallback para estouro: (1) tradução mais concisa, (2) re-síntese mais rápida dentro do limite de ~1,9× ("compressão" = re-síntese com speed nativo OU texto mais curto — NÃO atempo), (3) congelar e estender o slide abaixo dele (veja Time-density), (4) pegar emprestada a folga de um vizinho de baixa densidade; último recurso, limite rígido + fade de 30 ms no final (a legenda ainda carrega a linha completa).
Legendas em inglês aparecem SOBRE o vídeo, enormesO padrão SRT→libass usa PlayResY=288 → a fonte/margem escala ~4,4×. Emita ASS com PlayResY explícito = altura com padding. E letterbox (adicione uma barra inferior, Alignment=2) para que o inglês não colida com as legendas nativas queimadas da fonte (você não pode removê-las).
OCR Vision "precisa de um script personalizado"Não — pip install ocrmac; ocrmac.OCR(f, language_preference=["zh-Hans","en-US"]).recognize() retorna (text, conf, (x,y,w,h)) normalizado, origem canto inferior esquerdo.
Reconciliar ASR com a legenda na telaA legenda inferior É a verdade fundamental autoritativa para a narração — ótima verificação cruzada para o ASR. MAS os criadores colocam legendas de piada (absurdo ≠ fala); nunca substitua cegamente o ASR pelo OCR. Sinalize divergências, julgue cada uma.
ASR achata silenciosamente um trocadilho homofônicoA piada pode ser o homófono: 人工智能 (IA) falado como 人工痔能 ("tecnologia de hemorroidas"), ou 搁置 ("engavetar o projeto") como 割痔疮 ("remoção de hemorroida"). O Whisper "corrige" o trocadilho raro para a palavra comum, então a piada nunca chega à transcrição — e nenhuma correção de nome próprio a recupera. Os criadores geralmente escrevem o trocadilho na legenda queimada, então aqui o OCR não é uma verificação cruzada — é geralmente o único caminho de recuperação confiável (para um homófono escrito, a legenda vence; o oposto do caso de legenda de piada acima). Sinal: uma linha parece estranhamente literal, ou a reação/imagem não corresponde às palavras → faça OCR daquela legenda antes de traduzir.
Usar Whisper antes de verificar as legendas do YouTubeyt-dlp --list-subs custa 5s e compensa de três maneiras. (1) A tag <lang>-orig = o verdadeiro idioma de origem do vídeo; se já for o seu ALVO (ex.: en-orig), todo o pipeline é desnecessário — pare antes de baixar e usar o Whisper. (2) Uma faixa manual/criador (idioma de origem) geralmente vence o Whisper: pontuação real, nomes próprios corretos, sem [music] injetado. (3) Uma legenda automática -orig é um segundo ASR gratuito — diferencie-a contra o Whisper para revelar exatamente as linhas que precisam de correção humana. Medido em uma palestra de 16 min em inglês: 98,2% de concordância de palavras, mas os dois mecanismos divergiram em Arthur Andersen (YT, correto) vs Anderson (Whisper, errado) e ambos erraram um nome de marca (Saily → "Saylite"/"Saley") — a verificação cruzada sinaliza isso; nenhum mecanismo sozinho detecta. Armadilha: os outros 100+ idiomas em --list-subs são auto-TRADUÇÕES do YouTube, não faixas do criador — não confunda uma linha zh-Hant lá com uma fonte real em chinês.
Sobrepor cada caixa em chinêsEm vídeos de comentário, muito do "conteúdo" na tela (artigos, palestras incorporadas, tweets) já está em inglês com chinês sobreposto — sobrepor é redundante e poluído. Escopo para elementos apenas em chinês.
Sobreposição estática em texto rolanteA sobreposição por intervalo (posição média) não consegue rastrear rolagem contínua — o chinês fica descoberto. Precisa de OCR quadro a quadro + rastreamento de caixa; geralmente não vale a pena (esse conteúdo é do tipo já em inglês).
Manter clipes originais em inglês audíveisOnde a fonte reproduz clipes reais em inglês (entrevistas/demos), passe o áudio original em volume total nas lacunas; reduza-o (~0,1) apenas sob a dublagem.
Reutilizar scripts em um NOVO vídeoAdapte, mas verifique comprimentos/caminhos codificados. render_overlay.py derivava a duração do overlay de uma contagem de quadros fixa — em um vídeo mais longo, o overlay parava silenciosamente no meio. Derive a duração de len(glob('f1/f_*.png')), não de uma constante. Retraduza en.srt + translations.json por vídeo; a asserção de pareamento de índice + uma verificação pontual lado a lado detecta desalinhamento de tradução/chave.

Time-density: retemporize a linha do tempo, não apenas a dublagem

O inglês carrega ~1,5–2× menos bits/segundo que o mandarim/japonês, então uma dublagem fiel está sempre lutando por tempo de áudio em uma fonte densa. Comprimir a dublagem (velocidade nativa) é uma alavanca e atinge o limite de ~1,9× antes de soar apressado. A maior: a linha do tempo visual é elástica — retemporize-a para encontrar a dublagem. Três alavancas, classificadas da mais barata primeiro:

  • Tradução mais concisa primeiro (denso→mais curto). Reformule as linhas mais densas de forma mais curta. Grátis, não perde nada que o espectador veja, e a legenda queimada ainda carrega o significado completo se a dublagem cortar um pouco. Esta é a principal alavanca para tomadas de cabeça falante (você não pode congelar um rosto em movimento sem trepidação; re-cortar com B-roll geralmente está fora do escopo para um trabalho de localização no lugar).
  • Congele e estenda slides estáticos (compre tempo onde a pressão está). A dublagem corre mais forte exatamente quando o narrador está lendo uma captura de tela/slide — e esse quadro é estático, então segure-o por uma fração a mais em uma pausa natural para ganhar tempo de áudio. Quase invisível SE você respeitar três condições: (i) é uma edição de linha do tempo — tudo a jusante se desloca pela pausa, então insira o congelamento e regenere o tempo das legendas/dublagem/overlay contra a linha do tempo com pausa (ou segure todas as faixas juntas no mux), não apenas ancore ao tempo original; (ii) congele apenas onde o fundo de áudio também pausa — uma pausa sobre música contínua/som ambiente/áudio original dessincroniza o fundo (estenda/cruzfade, ou congele apenas sob a dublagem onde o fundo está baixo/silencioso); (iii) "estático" deve ser verdadeiramente estático — um cursor, cursor piscante, ponteiro laser ou webcam inserida no quadro quebra a ilusão. Faça muitas pausas pequenas, nunca um único arrasto longo (uma pausa de vários segundos parece um travamento/buffer).
  • Recupere folga de trechos de baixa densidade (o inverso — menos denso→denso). Introduções, encerramentos, panorâmicas lentas têm espaço extra; deixe a dublagem respirar lá, ou pegue essa folga emprestada para um trecho denso.

Por que isso funciona: densidade e congelabilidade se correlacionam. A narração é mais densa porque ele está explicando um slide — e slides são exatamente o que é congelável. Então a maior parte da pressão de tempo tende a cair onde você pode absorvê-la. Meça, não assuma: marque cada segundo como estático por movimento quadro a quadro (mean|quadro − anterior| em escala de cinza reduzida) — mas o limite é uma calibração por vídeo (ruído de codec, bitrate, fps, granulação tudo o move; ≈4/255 foi o valor de um vídeo), e uma média de quadro inteiro perde movimento localizado (cursor/cursor/ponteiro) → mascare a faixa de legenda e verifique uma região estática, não o quadro inteiro. Em seguida, intersecte a máscara estática com os blocos de dublagem rápida para ver quanta pressão é congelável. Em um vídeo explicativo de 10 min medido, um teto calmo de 1,4× precisava de ~14s recuperados e 74% disso estava sobre slides estáticos congeláveis (26% sobre a cabeça falante não congelável → texto mais conciso) — mas essa divisão é vídeo por vídeo. Ultrapassar o tempo de execução da fonte é aceitável para um arquivo independente; nada externo sincroniza com ele.

Pontos de decisão para levantar com o operador

  • Escopo visual: direcionado (apenas chinês, recomendado) vs completo (também parágrafos de artigo — degrada em rolagem).
  • Voz da dublagem: qual voz Kokoro grátis; ofereça pago (ElevenLabs) apenas se eles relaxarem a restrição de sem faturamento.
  • Áudio: substituição completa vs manter o original com volume reduzido sob a dublagem.
  • Esforço de ritmo: aceitar uma dublagem rápida (legendas carregam o significado completo) vs retemporizar para um teto calmo (texto mais conciso + congelar e estender slides — custa uma medição + re-mux). Ofereça o número da medição para que eles possam decidir.

Verifique (não confie — veja)

Amostre quadros do mp4 FINAL (Leia os JPGs) em: um momento de narração, um momento de slide/overlay, uma lacuna de clipe em inglês e a última linha — confirme sincronia da legenda, posicionamento do overlay, letterbox e duração A/V correspondente. Pixels queimam permanentemente. Amostre um momento de slide DENSO especificamente (onde a dublagem corre) — é aí que a sincronia/drift quebra primeiro; a legenda chinesa queimada naquele timestamp é seu oráculo de sincronia. (Você não pode testar o áudio sozinho — a sincronia é estrutural via a linha do tempo ancorada; diga isso e peça ao operador para a última verificação auditiva.)

Compõe com

hardsubbing-video (os footguns de queima ffmpeg/libass — etapa 8 deste skill).

Habilidades Relacionadas