Communitygithub.com

Localização de vídeo: dublagem em chinês com voz clonada

Substitua a voz em inglês de um vídeo por uma dublagem em chinês clonada do falante original, numa linha do tempo idêntica: mesma imagem, mesma duração, música de fundo mantida e legendas bilíngues gravadas, com checagens de duração, revisão a frio e audição.

O que é Localização de vídeo: dublagem em chinês com voz clonada?

Receita Localização de vídeo, passo 3 (a dublagem), de ChHsiching/video-dubbing-skill. Lê o vídeo bruto e uma rodada de legendas bilíngues e gera uma segunda versão sem tocar na primeira. O agente traduz para dublagem — frases completas dentro de um orçamento de caracteres por cue, não fragmentos de legenda — e roda as checagens: duração, revisão a frio, audição e revisão pós-gravação. A CLI `cook dub` faz o trabalho determinístico: Demucs mantém a música, IndexTTS2 clona a voz, cada fala é encaixada na janela original com atempo por cue e o ffmpeg grava legendas ZH+EN. Resultado: um MP4 dublado com a duração exata do original e SRTs zh/en para upload.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ChHsiching/video-dubbing-skill/tree/HEAD/skills/video-dubbing

Perguntar na sua IA favorita

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

Documentação

Substitua os vocais originais em inglês de um vídeo por dublagem em chinês em uma linha do tempo de identidade: o vídeo nunca é re-ajustado — cada quadro mantém seu timestamp original e a versão dublada tem exatamente a duração do vídeo bruto. O áudio sintetizado de cada sinal é ajustado à sua própria janela original (início do sinal → início do próximo sinal) com um atempo por sinal; a síntese, mais rápida ou mais lenta, cabe na janela. O resultado é uma segunda versão — mesma imagem na mesma velocidade, áudio em chinês, legendas bilíngues ZH+EN incorporadas.

Esta skill faz as duas partes criativas que a CLI não consegue: traduzir para dublagem (frases completas escritas dentro de um orçamento de caracteres, não a fragmentação de legendas) e executar os gates de qualidade (gate de comprimento, revisão a frio, gate auditivo, revisão pós-incorporação). A execução determinística (Demucs, IndexTTS2, montagem, reajuste de tempo, ffmpeg) é tratada pelo subcomando cook dub da CLI cook. Todos os scripts de estágio estão dentro do pacote cook (stages/dub/); cada invocação abaixo é um comando cook. pip install -U video-cook atualiza tudo de uma vez.

Quando usar esta skill

Você tem um vídeo que já possui:

  • Um arquivo de vídeo bruto (<output-root>/raw/<name>.raw.mp4) — o original, com vocais em inglês.
  • Uma execução de legendas bilíngues do video-subtitle — especificamente transcript/<name>.en.full.srt (a transcrição em inglês de frases completas, mesclada a partir de fragmentos do whisperX) e transcript/translations.txt.

Você quer uma versão dublada em chinês. Se você ainda não tem isso, execute video-download e depois video-subtitle primeiro — esta skill lê suas saídas.

O que você produz

Três produtos são gerados: cooked/<name>.dubbed.mp4 (vídeo bruto intacto, dublagem em chinês, legendas bilíngues incorporadas — duração idêntica ao bruto), cloud-srt/zh.dub.srt + en.dub.srt (legendas para upload). Todo o resto são arquivos de trabalho em dubbed/ — a árvore anotada abaixo mapeia cada um deles.

A execução não está concluída até que as verificações da Etapa 6 passem.

Estrutura de diretórios

Esta skill adiciona dubbed/ (diretório de trabalho) e escreve os produtos finais em cooked/ e cloud-srt/:

<output-root>/
├── raw/                            ← do video-download (esta skill o lê)
│   └── <name>.raw.mp4
├── transcript/                     ← do video-subtitle (esta skill lê + adiciona)
│   ├── <name>.en.full.srt          ← inglês de frases completas (a origem do script de dublagem)
│   ├── translations_dub.txt        ← esta skill escreve: uma linha em chinês por sinal
│   └── <name>.zh.dub.srt           ← esta skill escreve
├── cooked/                         ← vídeos finais estão aqui
│   ├── <name>.cooked.bar.mp4       ← do video-subtitle (intacto)
│   └── <name>.dubbed.mp4           ← produto desta skill
├── cloud-srt/                      ← legendas para upload estão aqui
│   ├── zh.srt / en.srt             ← do video-subtitle (intactas)
│   └── zh.dub.srt / en.dub.srt     ← legendas de upload desta skill
└── dubbed/                         ← diretório de trabalho desta skill
    ├── _reference/
    │   └── ref.wav
    └── _full/
        ├── _segments/              ← cache do IndexTTS2 por sinal
        ├── dub.wav                 ← a dublagem no relógio original
        ├── dubbing.srt             ← arquivo de trabalho (ZH, pré-encurtamento)
        ├── dubbing.short.srt       ← arquivo de trabalho (ZH, saída de encurtamento)
        ├── dubbing.merged.srt      ← arquivo de trabalho (ZH, pós-encurtamento; copiado para cloud-srt)
        ├── dubbing.en.srt          ← arquivo de trabalho (EN de frases completas)
        ├── dubbing.en.short.srt / dubbing.en.merged.srt  ← suas saídas de encurtamento e mesclagem
        ├── dubbing.bilingual.srt   ← arquivo de trabalho (união bilíngue; o que é incorporado)
        ├── dubbing.cooked.ass     ← arquivo de trabalho (saída ass, copiado para burn.ass)
        └── burn.ass                ← o ASS realmente incorporado

Regra: dubbed/ é o diretório de trabalho; cooked/<name>.dubbed.mp4 e cloud-srt/{zh,en}.dub.srt são os produtos. Nunca toque em raw/, transcript/<name>.zh.srt, cooked/<name>.cooked.mp4 ou cloud-srt/{zh,en}.srt — esses pertencem ao video-subtitle. Se esta skill falhar no meio, o produto cozido bilíngue ainda está completo.

O pipeline

Dois estágios após o trabalho criativo: synth e depois assemble, invocados através do cook:

cook dub synth    <root> <name> --python <indextts-venv>/Scripts/python.exe
cook dub assemble <root> <name> --python <indextts-venv>/Scripts/python.exe [--keep-subs]
# ou ambos:
cook dub full <root> <name> --python <indextts-venv>/Scripts/python.exe

As etapas abaixo descrevem o que cada estágio faz internamente (para que você possa verificar saídas e diagnosticar falhas); os comandos cook dub <stage> são como você os executa.

Etapa 0 — Resolver os ambientes

Existem dois ambientes Python em jogo, e confundi-los é o modo de falha que esta etapa existe para prevenir:

  • Ambiente do cook (Python do sistema ou ~/.venvs/video-tools/) — onde a CLI cook reside, com whisperX/yt-dlp/torch para o pipeline de legendas.
  • Ambiente do IndexTTS2 (~/Git/index-tts/.venv) — um venv separado contendo indextts, torch, demucs e whisperx (o pipeline de dublagem adiciona os dois últimos em cima do lockfile upstream). Essas dependências são pesadas e isoladas de propósito; não tente instalá-las no ambiente do cook.

O cook executa cada estágio de dublagem como um subprocesso sob o venv do IndexTTS2 via --python, então from indextts import ... resolve lá. Todo comando cook dub nesta skill leva --python <indextts-venv>/Scripts/python.exe. Resolva o caminho do venv uma vez (padrão ~/Git/index-tts/.venv) e reutilize-o para toda a execução.

0a. Verificar se ambos os ambientes estão acessíveis:

<cook-venv>/Scripts/cook doctor                                    # whisperX/yt-dlp/ffmpeg
<indextts-venv>/Scripts/python -c "from indextts.infer_v2_5 import IndexTTS2; import demucs, whisperx; print('ok')"   # indextts (v2.5) + demucs + whisperx

0b. Restrição de thread única. O IndexTTS2 deve ser executado com thread única (OMP_NUM_THREADS=1), ou produz áudio de baixa qualidade. O cook define isso internamente antes de importar o torch, então você não precisa exportá-lo.

Concluído quando o doctor do cook reporta whisperX/yt-dlp/ffmpeg instalados, o venv do IndexTTS2 importa indextts (v2.5) + demucs + whisperx, e você sabe o caminho absoluto para <indextts-venv>/Scripts/python.exe para passar como --python.

Etapa 1 — Separar vocais do vídeo bruto

O áudio original é uma faixa mixada (vocais + BGM + SFX). O Demucs o divide para que possamos extrair uma referência limpa e verificar BGM posteriormente.

cook dub separate <output-root> <name> [--model htdemucs] --python <indextts-venv>/Scripts/python.exe

O Demucs reside no venv do IndexTTS2, então --python aponta para lá. Use htdemucs (modelo único, ~3GB de RAM), não htdemucs_ft (conjunto de 4 modelos, ~20GB de RAM — estoura a memória em máquinas de 32GB). A qualidade é ligeiramente inferior, mas adequada para extração de referência.

No modo de primeiro plano (padrão), o cook move as faixas separadas para dubbed/vocals.wav + dubbed/no_vocals.wav automaticamente; no modo --detach você as move após o marcador de conclusão aparecer.

Concluído quando dubbed/vocals.wav E dubbed/no_vocals.wav existem com duração correspondente ao bruto ±0,5s.

Etapa 2 — Extrair o clipe de referência

O IndexTTS2 precisa de um clipe limpo de 14 a 30 segundos do falante original — ele lê no máximo os primeiros 15s, então uma janela de capacidade total é melhor que uma curta. O IndexTTS2 clona prosódia, não apenas timbre: o ritmo de entrega da janela se torna o ritmo de entrega de toda a dublagem. O seletor padrão pega o segmento de fala contínua mais longo, que tende a selecionar a passagem mais lenta e deliberada — muitas vezes errada. Prefira o scanner:

cook dub scan-reference <output-root> <name> \
    [--full-band] [--python <indextts-venv>/Scripts/python.exe]

Ele classifica janelas fixas de 15s por taxa de sílabas (filtradas por densidade e pausa) e corta os 3 melhores candidatos (mais cópias de banda larga de 48k com --full-band). A densidade é apenas metade da história — o IndexTTS2 também clona a prosódia da janela, então classifique os candidatos também por vivacidade: desvio padrão do F0 por pyin e faixa de semitons por janela (uma janela plana dubla plano; use librosa.pyin, NÃO detect_pitch_frequency, que relata sonoridade no silêncio). Autentique qualquer arquivo de referência legado antes de reutilizá-lo: um derivado reprocessado mantém sua incorporação de falante e estatísticas de pitch, mas perde correlação de forma de onda, então correlação próxima de zero NÃO significa "falante diferente" — pontue-o contra um clipe âncora com cook dub scan-reference --score <file> --anchor <anchor.wav> (áudio real do mesmo falante chega perto de 0,94; sínteses na faixa de 0,66-0,76 é a banda normal) e compare as estatísticas pyin. De qualquer forma: o ouvido do usuário escolhe a referência, sempre — sintetize as frases piloto uma vez por candidato (Etapa 3a), pré-selecione cada take com um ASR de modelo pequeno ida e volta (palavras perdidas sinalizam confusão; saída em chinês tradicional sinaliza um sotaque que a janela sangra no take), pontue com cook dub scan-reference --score, então entregue os wavs com correspondência de volume ao usuário.

Concluído quando dubbed/_reference/ref.wav existe, tem 14-30s e não tem gap de silêncio > 0,3s (ffmpeg -af silencedetect).

Etapa 3 — Traduzir para dublagem (o agente faz isso)

Aqui é onde a dublagem diverge das legendas. Não use translations.txt (a tradução de legendas) — ela segue os cortes de fragmentos do whisperX, que dividem frases. A dublagem precisa de frases completas para que o chinês flua naturalmente quando falado.

Leia <output-root>/transcript/<name>.en.full.srt (a transcrição em inglês de frases completas). Traduza cada sinal você mesmo, escrevendo em transcript/translations_dub.txt — uma linha em chinês por sinal em inglês, linha N = sinal N.

A regra do orçamento de caracteres — o núcleo da tradução de dublagem. O orçamento de cada sinal é janela em segundos × taxa de fala normal, fixado antes de você escrever: a janela é do início do sinal ao início do próximo sinal (janela + pausa seguinte), a taxa é medida, nunca assumida — cook dub measure-rate nos pilotos que o usuário escolheu (procedimento: Etapa 3a). Uma taxa assumida passa por todos os gates e dubla com segundos de silêncio morto: uma palestra de 45 minutos orçada a uma taxa assumida de 5,0 caracteres/s contra uma taxa real de 6,93 deixou 83 sinais com >2,5s de silêncio e custou uma re-síntese de 82 sinais. Escreva dentro do orçamento: um pouco acima está ok, notavelmente abaixo não está — um take curto agora mantém seu ritmo natural e deixa uma pausa para respirar, então texto abaixo do orçamento significa silêncio morto e texto acima do orçamento significa compressão audível. Recalibre em qualquer mudança de referência ou fator de duração: um orçamento calibrado para uma referência aposentada passa por todos os gates e ainda dubla com silêncio morto. Sintetize uma sonda estratificada (5-10 sinais típicos por falante em faixas de comprimento) e re-verifique o script em relação às janelas nas taxas medidas — procedimento em REFERENCE.md → "Rate recalibration". Como preencher um orçamento legitimamente (e o que "preencher" não tem permissão para inventar): REFERENCE.md → "Filling the char budget".

Princípios de tradução (além do orçamento):

  • Traduza pensamentos completos, não fragmentos. O inglês já são frases completas; seu sinal em chinês é um pensamento completo.
  • Mantenha termos técnicos em inglês onde desenvolvedores chineses o fazem — spec, plan, prototype, agent, token, skill, session, branch, route, etc. Veja REFERENCE.md → "Term retention list".
  • Mantenha inglês para qualquer coisa mostrada na tela — rótulos de UI, código, URLs, nomes de arquivos. Exemplos em REFERENCE.md → "Term retention list".
  • Traduza conceitos que têm nomes chineses padrão quando não são mostrados na tela — os exemplos trabalhados estão na lista de retenção de termos.
  • A contagem de linhas deve ser igual à contagem de sinais. A maneira sancionada de alterar contagens é o build_merge.py da Etapa 3a, que reescreve ambos os arquivos juntos.

Em seguida, gere o SRT de pré-montagem (timestamps herdados de en.full.srt):

cook dub make-srt <output-root> <name>

Auto-revisão — duas passagens, antes do gate mecânico: leia cada linha em voz alta em sua cabeça como uma frase falada (soa como algo que uma pessoa diria?); depois, escaneie a lista de termos abaixo em relação a cada linha (qualquer coisa na tela permanece em inglês, conceitos padrão vão para chinês). Estas são você verificando seu próprio trabalho; a revisão do subagente abaixo é a leitura a frio.

Gate de comprimento — mecânico (aritmética pura, leva um segundo):

cook dub gate <output-root> <name> --rate <medido chars/s>

Ele verifica cada linha em relação à sua janela de sinal de três maneiras: linhas curtas (≤8 sílabas — a armadilha de ritmo de narração do IndexTTS2, reescreva mais completo ou deixe a Etapa 3a fundir), erros de orçamento (fala estimada muito acima de sua janela — o texto deve ser cortado — ou muito abaixo — a janela fica com silêncio morto, preencha-a), e o total de cobertura (Σ fala estimada / Σ janelas — uma tradução uniformemente fina passa em cada verificação de linha e ainda dubla com longos silêncios; saudável 90-105%). --rate é obrigatório (o valor medido; --self-measure o deriva de takes existentes). Saída 1 lista as linhas e o veredito de cobertura; reescreva e execute novamente até passar. Uma linha acima do orçamento é corrigida reescrevendo mais curto ou fundindo-a com seu vizinho com cook dub merge — nunca deixando-a ser comprimida por atempo.

Gate de qualidade — revisão de subagente fan-out (obrigatório, antes da síntese). O gate auditivo e esta revisão são os únicos gates antes de horas de síntese. Faça um fan-out de um subagente com acesso de leitura tanto a <name>.en.full.srt quanto a translations_dub.txt, e peça para ele verificar, para cada sinal:

  1. Precisão da tradução — o chinês transmite fielmente o inglês? Nenhuma cláusula omitida, nenhum conteúdo adicionado (nada que o inglês não diga), nenhuma tradução incorreta.
  2. Ortografia de nomes próprios — nomes (pessoas, produtos, empresas) exatamente como a fonte os usa. "Claude" não "克劳德", "IndexTTS" não "索引TTS", a menos que um nome chinês padrão realmente exista.
  3. Legibilidade para TTS — o IndexTTS2 pronunciará isso naturalmente? Nenhuma sequência de caracteres estranha, nenhuma pontuação órfã

…

[truncado para tradução]

Habilidades Relacionadas