Communitygithub.com

hongliangzheng11/lyric-video-skill

Gere vídeos de letras bilíngues 1080×1920 na vertical com HyperFrames: fundo escuro e sonhador, um único objeto de vidro transparente que se deforma ao tocar as bordas, uma banda de animais na parte inferior e legendas com o texto original e tradução em chinês centralizadas.

O que é lyric-video-skill?

Esta skill automatiza a criação de vídeos de letras musicais no formato vertical 1080×1920 usando o framework HyperFrames. Ela é ideal para desenvolvedores e criadores de conteúdo que desejam produzir vídeos de letras com estilo visual consistente e profissional, sem precisar redesenhar a aparência a cada projeto. A skill suporta os agentes Claude Code, Cursor e Codex, e requer apenas um arquivo de áudio (MP3/WAV/FLAC) e o nome do artista como entradas obrigatórias, com letras oficiais sendo opcionais. Se o usuário fornecer letras oficiais, a skill as utiliza como prompt para uma re-análise por janela temporal, obtendo timestamps precisos sem adivinhar o texto. Caso contrário, ela usa o Whisper para transcrever o áudio e gerar as letras automaticamente. O fluxo de trabalho inclui etapas para criação do projeto, transcrição (suportando músicas monolíngues e multilíngues), alinhamento das letras, geração de movimento, renderização e verificação final, garantindo que cada linha de letra esteja sincronizada com o áudio real e que não haja erros de layout ou timing.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add hongliangzheng11/lyric-video-skill

Perguntar na sua IA favorita

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

Documentação

Linha de Montagem Padrão para Vídeo de Letra

Um estilo fixo já validado. O usuário só precisa fornecer o arquivo de áudio e o nome do cantor; todo o resto deve seguir este padrão, sem redesenho visual. Letras oficiais são opcionais: se fornecidas, siga o caminho rápido 3A (zero suposições de texto); caso contrário, siga o caminho de reconstrução 3B. Em ambos os casos, a linha do tempo deve ser baseada em medições reais.

Entrada / Saída

EntradaDescrição
ÁudioObrigatório. Qualquer MP3/WAV/FLAC, duração ilimitada
Nome do CantorObrigatório. Usado na abertura, logotipo constante e créditos finais
Letras Oficiais (opcional)Quando o usuário tiver letras oficiais, priorize: zero suposições de texto, mas a linha do tempo ainda deve ser totalmente baseada em medições reais (veja 3A). Se não fornecido, use Whisper para reconstrução (3B)
Nome da Música (opcional)Padrão: nome do arquivo; Artista - Título.mp3 remove automaticamente o prefixo do artista
Frase Tema (opcional)Uma linha em chinês abaixo do título na abertura; padrão: não exibida

Saída: <project>/renders/video.mp4 + renders/contact-sheet.jpg + transcript.json + NOTES.md.

Especificações Fixas (Não Alterar Sem Permissão)

  • Tela vertical 1080 × 1920, 30 fps, duração total igual à duração real do áudio (sem cortes, sem esticar, sem alterar velocidade).
  • Áudio: arquivo original; o framework ajusta o ganho uniformemente durante a renderização (data-volume="0.9").
  • Fundo: preto puro a azul-púrpura muito escuro, dois conjuntos de manchas de luz deslocadas desvanecem-se lentamente; não use filtros CSS em tela cheia (deixam costuras de blocos).
  • Corpo principal: apenas um corpo de vidro transparente, 8 contornos geométricos arredondados (esfera/elipse horizontal/elipse vertical/retângulo arredondado/losango/triângulo/pentágono/hexágono); ao bater na borda da tela, comprime 11% ao longo da normal → transforma-se em outro contorno em 0,94 s → continua flutuando. Linha do tempo única para toda a música; não reinicia na troca de letras.
  • Parte inferior: banda de animais pequenos (gato/urso/pinguim/raposa) em loop contínuo de 4,5417 s, alinhado ao fundo 1080×526, camada acima das manchas de luz do fundo e abaixo do corpo de vidro, mix-blend-mode: screen.
  • Legendas: bloco inteiro centrado opticamente no centro vertical da tela y≈960; texto original em inglês/outra língua em cima (Inter, tamanho adaptável à largura da linha), chinês em baixo (Songti SimSun, marrom quente #DDA97D); mesmo grupo desvanece-se.
  • Créditos sempre usam o nome do cantor; nenhuma etiqueta de parágrafo como VERSE / CHORUS / BRIDGE aparece na tela.

Parâmetros detalhados, cores, tamanhos de fonte e armadilhas estão em references/style-spec.md.

Fluxo

Seja HF = diretório raiz de instalação do HyperFrames (padrão G:\hyperframes), PY = Python com faster-whisper (padrão C:\Users\Admin\.workbuddy-ai\binaries\python\envs\hf\Scripts\python.exe), SK = diretório desta skill.

1. Criar Projeto

"$PY" "$SK/scripts/new_project.py" "<caminho_do_audio>" "<nome_do_cantor>" [--title "nome_da_musica"] [--tagline "uma_linha_em_chines"] [--root G:/hyperframes/videos]

Produz o caminho absoluto do projeto; anote-o. Ele: cria um diretório único → copia o áudio → converte para WAV mono de 16 kHz → executa o analyze-beatgrid.py oficial para gerar audiomap.json → copia o sprite da banda e GSAP → escreve project.json.

Nunca sobrescreva um diretório de projeto existente; modificar um trabalho já entregue requer criar um novo projeto.

2. Transcrição

"$PY" "$SK/scripts/transcribe.py" "<projeto>" --model medium.en --lang en

CPU int8: uma música de 3-4 minutos leva cerca de 3-6 minutos. Para músicas não-inglesas, troque --lang pelo idioma correspondente e remova .en de --model. Saída: whisper_raw.json (timestamps de segmento e nível de palavra).

Músicas multilíngues (inglês + japonês, inglês + coreano, etc.) não use transcribe.py: --lang trava um idioma, e o outro idioma será forçado a ser transcrito como o primeiro — o resultado parece fluente mas está todo errado, mais perigoso do que não resolver. Em vez disso, use detecção automática de idioma por janela:

"$PY" "$SK/scripts/transcribe_mixed.py" "<projeto>" --model "C:/Users/Admin/.cache/whisper-manual/large-v3-turbo"

Ele decodifica com janelas de 14 s / passo de 10 s, cada janela detecta seu próprio idioma, mantém apenas as palavras do centro da janela (sobreposições descartadas, sem duplicação), imprime um mapa de idiomas e escreve whisper_mixed.json. Veja o mapa de idiomas primeiro: as posições onde o idioma muda são geralmente os limites das estrofes. Nota: modelos .en (medium.en / small.en) são modelos exclusivamente ingleses; fisicamente não podem produzir japonês; músicas multilíngues devem usar modelos multilíngues.

Para o caminho 3A (com letras oficiais), este passo é opcional: a linha do tempo é baseada na re-scan com prompt, mas para músicas multilíngues ainda é recomendado executar transcribe_mixed.py para ver o mapa de idiomas, a fim de determinar se cada janela deve usar --lang en ou --lang ja.

3. Escrever o Arquivo Fonte de Letra (Este Passo Deve Ser Feito Manualmente)

Primeiro, decida qual caminho seguir, depois escreva <project>/lyrics_source.json.

3A O usuário forneceu letras oficiais (caminho preferido)

  • Use o texto das letras oficiais sem alterações: slot en = texto original oficial (frases em inglês em inglês, frases em japonês em japonês, kanji/kana escritos como estão), slot zh = tradução linha por linha.
  • Linha do tempo não vem da transcrição completa: use as letras oficiais como initial_prompt para re-scan por janela para obter timestamps de nível de palavra (veja 3.5), escreva start/end explícitos para cada linha; align_lyrics.py usará o canal manual para ancorar linha por linha.
  • Se as letras oficiais e o que a re-scan ouve não coincidirem → adote sempre as letras oficiais, liste as diferenças em NOTES.md para o usuário confirmar. Três tipos comuns: forma padrão vs erro de digitação (不甲斐ない / 不甲埋ない), palavras com som semelhante (束の間の / 明日の間の), consoantes surdas mal ouvidas (smiling / falling).
  • Se nas letras oficiais duas linhas são cantadas de uma vez e cada uma tem menos de 1 segundo → una as linhas em uma única linha de legenda (texto inalterado, apenas justaposto), escreva a tabela de união em NOTES.md.
  • Onomatopeias/improvises ("Yeah,", humming, assobios) não presentes nas letras oficiais → não coloque legendas; não invente.
  • Estrutura conforme abaixo:
{
  "audio": "Artist - Title.mp3",
  "models": ["large-v3-turbo — prompted window re-scans, official lyrics as initial_prompt"],
  "lines": [
    {"en": "Oh my god, they're coming again", "zh": "哦天哪,他们又来了", "start": 6.36, "end": 9.10, "lang": "en", "conf": "high"}
  ]
}

3B Sem letras oficiais (caminho de reconstrução)

Leia whisper_raw.json (ou whisper_mixed.json para músicas multilíngues) e escreva o arquivo fonte:

{
  "audio": "Artist - Title.mp3",
  "models": ["faster-whisper medium.en — full track, word timestamps"],
  "lines": [
    {"en": "Sometimes I lay under the moon", "zh": "有时我躺卧在月光之下"},
    {"en": "And thank God I'm breathing", "zh": "感谢上天让我仍在呼吸"}
  ]
}

Requisitos comuns a ambos os caminhos:

  • Cada linha = uma frase cantada real, seguindo a divisão oficial; linhas muito longas do Whisper devem ser divididas.
  • Ortografia em inglês conforme as letras oficiais (preserve apóstrofos em 'Cause / I've, etc.), não copie erros do Whisper.
  • Tradução para chinês linha por linha, tom consistente com a música, sem pular linhas, sem unir, sem texto placeholder.
  • Refrões repetidos devem ser escritos todas as vezes (não use "idem").
  • Se uma frase for coberta pelo acompanhamento e o alinhamento automático estiver claramente deslocado, adicione timestamps explícitos (ouça o áudio antes de preencher): {"en": "...", "zh": "...", "start": 13.22, "end": 16.80}.
  • Música em chinês/música instrumental: para música em chinês, coloque o texto original em en e deixe zh como string vazia; a tela mostrará apenas uma linha; música instrumental não se aplica a esta skill.
  • Músicas multilíngues: slot en deve conter o texto original no idioma real da frase (frases em inglês em inglês, frases em japonês em japonês, kanji/kana escritos como estão), slot zh com a tradução em chinês. A tela já é "texto original + chinês" em duas linhas; a mistura não quebra o layout; a linha em inglês do template já tem fallback com Yu Gothic UI / Yu Gothic / Meiryo, então kana e kanji aparecem corretamente.

3.5 Re-scan com Prompt: O Coração da Precisão da Linha do Tempo

A transcrição completa geralmente é imprecisa para músicas rápidas, canto misturado ou frases rápidas. Usar letras conhecidas como initial_prompt para re-scan por janela é o método de maior precisão — a qualidade do prompt determina diretamente a precisão do re-scan: letras oficiais > letras adivinhadas > sem prompt. Pode ser colocado em um script rescan_all.sh para executar em lote a música inteira:

"$PY" "$SK/scripts/rescan.py" "<projeto>" --from 6.0 --to 20.0 \
    --model "C:/Users/Admin/.cache/whisper-manual/large-v3-turbo" \
    --lang en --prompt "<texto original das letras oficiais para esta janela>"

Pontos-chave:

  • Divida a música inteira em janelas de 20–26 s, com sobreposição de cerca de 0,5 s entre janelas, re-scan por janela; large-v3-turbo CPU int8 leva cerca de 5–10 s por janela.
  • Para músicas multilíngues, cada janela é decodificada duas vezes (en e ja) e apenas os timestamps de palavra consistentes em ambas são adotados; palavras que aparecem em apenas um caminho são verificadas com o outro.
  • Frases com início pouco claro ou que começam cedo demais adicione uma janela estreita de 2 s para bloquear (ex.: --from 37.2 --to 39.2 para bloquear apenas o início de uma frase); o início de uma janela de partição pode ser influenciado pelo final da frase anterior.
  • Alucinações: ocasionalmente, o re-scan pode repetir a mesma frase inteira 15+ vezes → descarte essa janela, troque para o canal de outro idioma ou reduza a janela e re-execute; pegue apenas os timestamps limpos e únicos; não inclua timestamps de alucinação no arquivo fonte de letras.
  • Cada re-scan salva rescan_<from>-<to>.json e imprime o início e fim de cada palavra na janela. Isso é uma segunda decodificação, não uma estimativa; os números são escritos diretamente em lyrics_source.json como start/end.
  • Para trechos cobertos pelo acompanhamento, transformados em ooh, unidos em um grande bloco ou frases repetidas engolidas, use primeiro este método para obter valores de cobertura; trocar o modelo (small.en / medium.en) também é eficaz.

4. Alinhamento + Geração

"$PY" "$SK/scripts/align_lyrics.py" "<projeto>"
"$PY" "$SK/scripts/motion.py" "<projeto>"
"$PY" "$SK/scripts/gen_storyboard.py" "<projeto>"
"$PY" "$SK/scripts/build_frame.py" "<projeto>"
"$PY" "$SK/scripts/make_index.py" "<projeto>"

align_lyrics.py imprime uma tabela de timestamps linha por linha e faz duas verificações rigorosas:

  • Se houver frases no início/fim que não correspondem → erro e saída, listando quais frases são (não mascara com timestamps adivinhados).
  • Se houver frases no meio que não correspondem, ou duas frases com o mesmo início, ou uma frase comprimida abaixo de 0,5 s → imprime REVIEW e sai com código 2.

Nestes casos, volte ao passo 3.5 para adicionar valores de cobertura, até que a saída seja OK: every line anchored to a real sung timestamp. Não pule este passo para renderizar. No caminho 3A, todas as linhas têm start/end explícitos (canal manual), devem estar totalmente ancoradas, 0 gaps preenchidos; no caminho 3B, depende de correspondência de palavras; linhas sem correspondência devem ter timbers adicionados conforme 3.5.

A semente aleatória de motion.py é determinada por "nome do cantor + nome da música" — a mesma música sempre produz o mesmo caminho ao re-executar; músicas diferentes produzem caminhos diferentes.

5. Verificação

cd "<projeto>"
node "$HF/packages/cli/bin/hyperframes.mjs" check .
node "$HF/packages/cli/bin/hyperframes.mjs" snapshot . --at "3,20,60,120" --no-end -o build/shots

Deve ter: lint / runtime / layout / motion 0 erros, contraste passando WCAG AA. Depois, veja os screenshots: se o corpo de vidro está completo, as letras estão centralizadas, a banda está na parte inferior, se há bolhas ou etiquetas de parágrafo extras. composition_file_too_large é um aviso de estilo para arquivos de quadro com mais de 300 linhas; é aceitável (inevitável em design de linha do tempo única).

6. Renderização + Aceitação

node "$HF/packages/cli/bin/hyperframes.mjs" render . --skill=music-to-video -q delivery -o renders/video.mp4 --fps 30
"$PY" "$SK/scripts/verify.py" "<projeto>"

verify.py verifica resolução/framerate/desvio de duração (erro se mais de um quadro) e gera uma folha de contato. Veja a folha de contato, confirmando que abertura, versos, refrão, repetições e final têm cenas, e as legendas não têm lacunas ou desalinhamentos.

Por fim, escreva NOTES.md (especificações, origem da linha do tempo, comandos para reproduzir, registros de verificação) e entregue o vídeo final e a folha de contato ao usuário.

Disciplinas Rígidas

  • Não use BPM/grelha de batidas para calcular timestamps de letras; timestamps devem vir apenas de medições reais do Whisper (incluindo re-scan com prompt) ou cobertura manual por audição.
  • Letras oficiais fornecidas pelo usuário têm precedência sobre qualquer resultado de modelo; em caso de conflito, adote as letras oficiais e liste as diferenças em NOTES.md para o usuário confirmar.
  • Não altere resolução, framerate, duração, créditos ou posição das legendas porque "parece melhor".
  • Não declare sincronia áudio-vídeo sem verificação; cada música deve ser verificada quadro a quadro.
  • Material faltando, ferramentas indisponíveis, conflitos de especificação → relate claramente; não use dados estimados para mascarar resultados.
  • Projetos entregues e seus arquivos fonte são considerados somente leitura; revisões devem criar um novo diretório.

Dependências do Ambiente

  • HyperFrames: node <HF>/packages/cli/bin/hyperframes.mjs (inclui skills/music-to-video/scripts/analyze-beatgrid.py).
  • Python: faster-whisper, librosa, soundfile, numpy, scipy, pillow. Se faltar: python -m venv <env> && <env>/Scripts/pip install faster-whisper librosa soundfile numpy scipy pillow.
  • Modelos Whisper: passar o nome do modelo baixa automaticamente; também pode apontar para um diretório local (comum: C:\Users\Admin\.cache\whisper-manual\medium.en; para re-scan com prompt, prefira C:\Users\Admin\.cache\whisper-manual\large-v3-turbo, CPU int8 música inteira ~48 s, janela única 5–10 s).
  • ffmpeg / ffprobe devem estar no PATH.

Armadilhas Conhecidas

  • Não use <video> para a camada da banda: o hyperframes render local no Windows falha ao ler os quadros extraídos do diretório vinculado ao diretório de compilação (erro ENOENT ... __hyperframes_video_frames/*/frame_00001.jpg). Use sprite.
  • CSS filter: hue-rotate() em tela cheia deixa costuras verticais na renderização; use duas camadas de manchas de luz com crossfade.
  • Templates HTML com data-composition-id não podem ficar no diretório raiz do projeto (dispara multiple_root_compositions); coloque em build/.
  • Fontes chinesas devem ter declaração explícita @font-face com local("SimSun"), senão o lint reporta font_family_without_font_face.
  • Alucinações em re-scan: algumas janelas repetem a mesma frase inteira 15+ vezes (ex.: "永遠の行方はどこにある?" ×15) → descarte essa janela, troque para o canal en cruzado ou reduza a janela e re-execute; não inclua timestamps de alucinação no arquivo fonte de letras.
  • Letras oficiais vs re-scan inconsistentes: adote as letras oficiais e liste a tabela de comparação em NOTES.md para o usuário confirmar; não altere o texto oficial por conta própria.
  • Linhas rápidas unidas: se duas linhas nas letras oficiais são cantadas de uma vez e cada uma tem menos de 1 segundo, una as linhas em uma única linha de legenda (texto inalterado, apenas justaposto); escreva a tabela de união em NOTES.md.
  • Falha no carregamento de fontes headless (Yu Gothic UI reporta FAILED ao extrair quadros) não é grave: fontes com src: local() que o sistema tiver geralmente são encontradas pelo navegador; a próxima fonte na lista de fallback também servirá; veja os screenshots primeiro antes de decidir o que fazer.

Habilidades Relacionadas