Série de Vídeos de Comédia e Crítica Social em Fundo Branco (Desenho à Mão)
Um vídeo = um roteiro + um conjunto de storyboards + uma trilha de áudio + uma capa + um pacote de publicação. Tudo é desenhado com o mesmo conjunto de primitivas gráficas e fontes, garantindo que cada episódio da série tenha um estilo consistente e que a capa e o vídeo principal não sofram nenhuma deriva visual.
Contrato de Entrega
Cada episódio deve entregar estes 5 grupos de arquivos, sem exceção:
| Produto | Arquivo | Especificação |
|---|---|---|
| Vídeo final com legendas | out/<título>_comedia_legendado.mp4 | 1080×1440, 30fps, H.264+AAC, aproximadamente 68s |
| Vídeo final sem legendas | out/<título>_comedia_sem_legendas.mp4 | Mesmo acima, removendo a camada de legendas |
| Arquivo de legendas | out/<título>.srt | Linhas com ≤ 16 caracteres, tempos crescentes e sem sobreposição |
| Capa 3:4 | out/<título>_capa.png | 1080×1440, usando o mesmo conjunto de linhas e fontes do vídeo principal |
| Material para WeChat Channels | project_*/publish.md + publish.json | 3 opções de título, 1 versão de descrição, 5–8 hashtags, 1 comentário fixado |
Além disso, anexe out/<título>_preview.png (tira com quatro quadros-chave) para que o usuário possa ter uma visão geral do episódio em uma única tela.
Ambiente
Python 3.10+, Pillow, NumPy, ffmpeg/ffprobe. Crie um ambiente virtual primeiro, sem modificar o Python do sistema:
python3 -m venv .venv && .venv/bin/pip install -r "$skill_dir/scripts/requirements.txt"
No macOS, o ffmpeg geralmente não está no PATH padrão; primeiro execute export PATH="/opt/homebrew/bin:$PATH".
A dublagem usa mcode-tools (MiniMax TTS/ASR) e requer que a skill mcode-tools-master esteja no PATH.
Se o comando python3 apresentar o erro "You have not agreed to the Xcode license agreements" (código de saída 69), significa que o Python do sistema não está configurado corretamente. Use um interpretador alternativo para criar o ambiente, por exemplo:
/opt/homebrew/bin/python3.13 -m venv .venv. Não tente modificar a licença do Xcode.
Fluxo de Trabalho
1. Definir o Tema e o Tom da Série
Episódio único: basta dar uma direção de humor. Vários episódios: defina para cada um um tom cômico exclusivo, sem repetir o mesmo tipo de piada com roupagem diferente.
- Fluxo de autodepreciação absurda (o próprio narrador vai ficando cada vez mais absurdo)
- Reviravolta em diálogo (duas pessoas conversando, a última frase vira o jogo)
- Observação fria (comédia de observação, humor seco e contido)
- Premissa absurda (levar uma premissa ridícula a sério)
Em uma mesma série, pelo menos dois tons diferentes devem estar próximos. A linguagem visual pode ser compartilhada, mas o ritmo narrativo não deve ser repetitivo.
2. Escrever o Roteiro
Leia [references/writing-style.md]. Critérios rígidos:
- Uma frase por cena, aproximadamente 40–45 frases, 480–520 caracteres, duração total de aproximadamente 68s (número de caracteres ÷ 7,4 ≈ segundos).
- Cada piada deve ter uma ação visível ou uma mudança de adereço para ser concretizada, não pode depender apenas da legenda.
- O final deve inverter a relação entre os personagens e deixar uma fala que possa ser capturada como print sozinha.
- Escreva no formato JSON:
{"title": ..., "target_seconds": 68, "segments": [{"scene": ..., "text": ..., "red": [...]}]}sceneé o ID da cena,redsão as palavras a serem destacadas em vermelho (devem aparecer exatamente como estão emtext).
3. Dividir os Storyboards
"$python_bin" "$skill_dir/scripts/build_segments.py" --story story.json --out project_ep2
As legendas são cortadas nos sinais de pontuação em linhas de ≤ 16 caracteres; o renderizador não suporta linhas com mais de 17 caracteres. O ponto de corte deve ser escolhido próximo a 10 caracteres, evitando quebrar palavras (por exemplo, "pagamentoantecipado" não pode ser cortado em "pagamentoante" e "cipado"); frases curtas entre aspas não são divididas, e não podem ser geradas linhas que comecem com 」. O script valida se as palavras em vermelho estão nas legendas, se a divisão não perdeu caracteres, se não surgiram legendas vazias com apenas pontuação, e imprime a duração estimada: caracteres ÷ 7,4 ≈ segundos. Se o desvio for superior a ±10% do alvo, um aviso será emitido — ajuste adicionando ou removendo frases, não tente compensar alterando a velocidade da fala.
4. Desenhar os Storyboards
No arquivo project_ep2/scenes.py, escreva as funções scene_<id>(c, t, d) e redefina o dicionário SCENES no final do arquivo (contendo apenas os IDs deste episódio). As primitivas de desenho estão em scripts/render/doodles.py.
person(c,x,y,s,expr,boss,pose,t,arms,legs): centro da cabeça em (x,y), corpo até y+307*s,exprpode serdead/sad/happy/angry/shocked/sleep,posepode serstand/shrug/point/phone/pockets/walk.woman(c,x,y,s,expr,t): figura materna (coque + vestido).speech(c,x,y,w,h,tail,size): balão de fala;c.text((x,y),'texto',size)usa ancoragem central.c.curveaceita apenas 4 pontos de controle;c.textnão suporta contorno nem múltiplas linhas.
Após fazer as alterações, passe por duas verificações:
"$python_bin" "$skill_dir/scripts/check_overlap.py" project_ep2/scenes.py # Auditoria de layout estático
"$python_bin" "$skill_dir/scripts/check_project.py" project_ep2 # Verificação da lista de contato
check_overlap.py detecta texto sobreposto a personagens, textos sobrepostos entre si e elementos fora da área de segurança. Ele já identifica duas situações que "parecem sobreposição mas não são": troca de palavras mutuamente exclusivas em if/else e blocos de fundo branco cobrindo elementos antigos. Portanto, os problemas reportados são, em sua maioria, reais — se o código de saída não for 0, corrija primeiro, não renderize diretamente.
check_project.py primeiro verifica as legendas e depois gera a lista de contato: as legendas, quando concatenadas, devem formar exatamente a mesma frase do roteiro (pontuação ajustada manualmente é permitida, mas não pode haver caracteres a mais, a menos ou palavras trocadas); legendas vazias (sem texto) também não são permitidas. Se falhar, o script sai imediatamente, sem desperdiçar tempo renderizando a lista de contato.
Para sobreposições que devem ser mantidas (por exemplo, um crachá desenhado sobre o personagem), registre-as explicitamente em scenes.py:
OVERLAP_ALLOW = {"three_years", "me_too"}
A lista de contato deve ser revisada cena por cena: a imagem corresponde à fala? O adereço está claro?
5. Dublagem
"$python_bin" "$skill_dir/scripts/build_voice.py" --project project_ep2 --speed 1.5 --gap 0.10
A síntese frase por frase é o ponto-chave deste fluxo: cada fala é sintetizada individualmente por TTS, o silêncio inicial e final é cortado e, em seguida, as falas são concatenadas com um intervalo fixo. Dessa forma, os tempos de início e fim de cada fala são conhecidos, e o asr.json é construído diretamente com base nesses tempos, garantindo que as legendas estejam perfeitamente alinhadas, sem necessidade de ASR em nível de palavra.
- O timbre padrão é
lengdan_xiongzhang(colega mais velho e frio). Se o usuário especificar outro, use o informado. - O TTS tem limitação de taxa de curto prazo (HTTP 429). O script usa um intervalo fixo de 10 segundos para repetir — intervalos fixos são mais eficazes do que backoff incremental.
- Um episódio único tem aproximadamente 40–45 falas, levando cerca de 15 minutos no total, executado em segundo plano.
- Após a síntese, faça uma verificação com
scripts/tts.py asr --file project_ep2/voice.wav. - Para erros de reconhecimento de fonação semelhante (ex: "ban shi / ban shi shi"), altere apenas os caracteres no resultado do ASR, não mude o roteiro nem regrave.
6. Linha do Tempo, Renderização e Verificação
"$python_bin" "$skill_dir/scripts/deliver.py" project_ep2 <título> --target 68
"$python_bin" "$skill_dir/scripts/verify.py" project_ep2
deliver.py calcula o atempo inversamente proporcional à duração alvo (velocidade = áudio original / (alvo - silêncio final)), gera a linha do tempo, as legendas, a mixagem de áudio, renderiza as versões com e sem legendas, e arquiva o vídeo final e o SRT em out/.
verify.py verifica: parâmetros de codificação, decodificação do vídeo completo, temporização e comprimento das legendas, e audição do ASR. A verificação só é considerada concluída quando todos os itens estão verdes; falhas de decodificação ou problemas de temporização nas legendas devem ser corrigidos e o vídeo renderizado novamente.
7. Capa
A capa não usa imagens geradas por IA, mas sim o mesmo conjunto de primitivas gráficas e fontes do vídeo principal, garantindo zero deriva de estilo.
No arquivo project_ep2/cover.py, escreva a função illustration(c) (as primitivas de desenho já estão injetadas no namespace).
No arquivo project_ep2/cover.json, escreva as linhas de texto:
{"lines": [
{"text": "Encontro às escuras", "size": 146, "y": 170, "red": []},
{"text": "Minha mãe arranjou sete", "size": 96, "y": 312, "red": ["sete"]},
{"text": "Conhecer os pais e a avó", "size": 64, "y": 1196, "red": []},
{"text": "Oitenta e sete e não enche o saco", "size": 64, "y": 1280, "red": ["enche o saco"]}
]}
"$python_bin" "$skill_dir/scripts/make_cover.py" project_ep2
As regras de layout estão em [references/cover-design.md]. A capa deve ser visualizada separadamente antes da entrega.
8. Material de Publicação para WeChat Channels
Primeiro, colete os insumos; depois, escreva o texto:
"$python_bin" "$skill_dir/scripts/make_metadata.py" project_ep2
O script imprimirá o roteiro completo, as palavras em vermelho, as palavras de alta frequência e as três últimas falas. Com base nisso, escreva:
- 3 opções de título, com emojis de atração, cada uma com no máximo 22 caracteres (idealmente; acima disso ainda é aceitável, limite máximo de 100 caracteres).
- 1 versão final da descrição, com 2–3 linhas, a primeira linha sendo o gancho, e as hashtags
#hashtagincorporadas no texto. - 5–8 hashtags, que devem aparecer todas na descrição (o script validará isso).
- 1 comentário fixado, para complementar ou fazer autodepreciação.
Depois de escrever:
"$python_bin" "$skill_dir/scripts/make_metadata.py" project_ep2 \
--titles "Título Um" "Título Dois" "Título Três" \
--desc "Texto da descrição #hashtag1 #hashtag2" \
--tags "hashtag1" "hashtag2" \
--comment "Comentário fixado"
Detalhes das regras em [references/publish-channels.md]. Os artefatos gerados são publish.md e publish.json.
Restrições Rígidas
- Canvas 1080×1440 (3:4), 30fps, fundo branco puro, contornos de 4–6px em preto, cabeça grande e corpo fino.
- O conteúdo principal deve estar concentrado em y=400–1050, com espaço em branco acima; a faixa de legendas começa em y=1084, tamanho mínimo da fonte 54.
- Legendas usam a fonte Xingkai (行楷), texto branco com sombra suave escura, palavras-chave das piadas em vermelho.
- Cada linha de legenda tem no máximo 16 caracteres; o renderizador não suporta linhas maiores.
- Não incorpore o texto da legenda na imagem; as legendas são renderizadas em uma camada separada.
- A capa deve usar exatamente o mesmo conjunto de fontes e linhas do vídeo principal; não é permitido mudar o estilo.
- Mantenha os vídeos já entregues; para alterações no roteiro, use um novo diretório de projeto, não sobrescreva os episódios já entregues.
Tratamento de Falhas
- TTS retornando 429 repetidamente: o script já faz até 40 tentativas com intervalo fixo. Se ainda assim falhar, reduza a velocidade para 1.4 e tente novamente, ou execute em lotes (
--limit Npara continuar, o cache ignorará as falas já sintetizadas). prepare.pyrelatando inconsistência no ASR: significa que oasr.jsonnão corresponde ao roteiro, geralmente porque o roteiro foi alterado sem regravar o áudio. Reexecutebuild_voice.py. Não use--allow-asr-mismatchpara contornar o problema.render.pyrelatando legenda muito longa: alguma legenda ultrapassou 16 caracteres. Volte aobuild_segments.pye ajuste as regras de divisão.check_overlap.pysaindo com código diferente de 0: corrija as coordenadas uma a uma, de acordo com o ID da cena reportado, até que o código de saída seja 0.- Não considere a verificação de áudio concluída sem ouvir tudo; não considere a visualização completa sem assistir ao vídeo inteiro. O registro de entrega deve conter apenas as verificações realmente realizadas.
Referências
- references/writing-style.md — Como escrever o roteiro e projetar as piadas
- references/series-plan.md — Planejamento da série e diferenciação entre episódios
- references/cover-design.md — Regras de layout da capa
- references/publish-channels.md — Regras para o material de publicação no WeChat Channels
Notas para a plataforma Windows (win32)
Procedimentos equivalentes no Windows:
- Ambiente virtual:
py -3 -m venv .venv, em seguida use.venv\Scripts\python.exeno lugar de$python_bin. - Dependências:
.venv\Scripts\pip.exe install -r "<skill_dir>\scripts\requirements.txt". - ffmpeg/ffprobe: instale diretamente no PATH (ex.:
winget install Gyan.FFmpeg), não é necessário adicionar/opt/homebrew/bin. No entanto, os caminhos do ffmpeg emscripts/deliver.py,scripts/make_preview.pyescripts/verify.pyestão codificados como caminhos absolutos do macOS; altere paraffmpeg/ffprobepara torná-los multiplataforma. scripts/build_voice.pydepende demcode-toolsno PATH e docurl. O Windows 10 1803+ já vem com curl integrado; se estiver ausente, useInvoke-WebRequest -OutFile <caminho> <url>como substituto.- Separadores de caminho: todos os scripts usam
pathlib; ao passar argumentos, forneça o caminho entre aspas.