clipwise: vídeo longo → Shorts verticais
Tudo roda localmente (CPU é suficiente; CUDA é usado para transcrição quando presente).
SKILL_DIR abaixo significa a pasta onde este arquivo está. Todos os comandos são
python3 SKILL_DIR/scripts/run.py ...; os scripts alternam para o venv do clipwise automaticamente.
Os jobs são gravados em ~/clipwise-work/<job>/ ($CLIPWISE_WORK), ou em --workdir DIR.
0. Verificação de configuração (toda sessão, uma vez)
python3 SKILL_DIR/scripts/run.py check
Deve terminar com ready. Se não, informe ao usuário que o clipwise precisa de uma configuração única (cerca de
2 GB: pacotes Python mais o modelo whisper), peça para ele ler SKILL_DIR/setup.sh e
execute bash SKILL_DIR/setup.sh assim que ele concordar. Se faltar ffmpeg ou Python 3.10+: o setup.sh imprime
o comando de instalação para o sistema operacional dele; não instale pacotes do sistema sem perguntar.
Fluxo de trabalho
- Preparação (baixar + transcrever, um comando):
Saída na pasta do job:python3 SKILL_DIR/scripts/run.py prep "<caminho ou link>" --job <nome> [--start S --max-seconds N] [--cookies cookies.txt] [--model large-v3-turbo] [--language xx]source.mp4(primeiro fluxo de vídeo + áudio, SDR, CFR 30 quando recodificado),probe.json,transcript.txt(uma linha[início-fim] (wN) textopor segmento, em segundos da fonte),transcript.json,words.tsv. Para vídeos longos, use--start/--max-secondsna parte que vale a pena recortar; a transcrição leva cerca de 0,6-1x o tempo real na CPU. - Escolha os momentos você mesmo. Leia
transcript.txt(e quaisquer linhas# WARNINGno topo) comSKILL_DIR/references/viral-rubric.md. Escreva<job>/picks.json: cada escolha de 10 a 50 s, gancho primeiro, final limpo com payoff. Quantidade: veja a regra abaixo. - Obtenha aprovação antes de renderizar. Mostre uma linha por escolha: timestamps, gancho, título, uma linha explicando o porquê. Renderizar leva cerca de 1-2 minutos por clipe em uma CPU pequena. Se você escreveu texto de legenda manualmente (fala não inglesa ou mista), mostre essas linhas também.
- Renderize:
Por escolha empython3 SKILL_DIR/scripts/run.py render --job <nome> [--fast] [--only 2] [--music bed.mp3]<job>/out/:clip_<id>.mp4,clip_<id>.txt(título, descrição, comentário fixado, hashtags, porquê),clip_<id>.json(números do probe, layout, cobertura facial, SFX, temporizações),clip_<id>_cutmap.json,clip_<id>_sheet.png.--fast= qualidade de pré-visualização. - Olhe cada
clip_<id>_sheet.pngcom sua ferramenta de imagem/visão (10 quadros; linha vermelha = y 1620, interface da plataforma abaixo dela). Verifique: rosto no quadro, legendas legíveis, legendas sem sobrepor o rosto, nada importante abaixo da linha vermelha, cores não desbotadas. Corrija (escolhas, substituições de legenda,--layout,--font-size) e re-renderize com--only <id>. - Entregue os caminhos dos MP4 e o conteúdo dos
.txt. Ofereçarun.py clean --job <nome>(excluisource.mp4e diretórios tmp, mantémout/).
Quantos Shorts por vídeo
-
O usuário definiu um número ("Faça 5 Shorts a partir de "): faça exatamente esse número. Se o vídeo não tiver tantos momentos fortes, diga antes de renderizar e proponha o número honesto ("Encontrei 3 momentos que passam na lista de verificação; os outros 2 seriam fracos").
-
Nenhum número fornecido: dimensione conforme a duração da fonte (ou da janela transcrita):
duração da fonte Shorts abaixo de 5 min 1-2 5-15 min 3-5 15-45 min 5-8 45 min+ (podcast, palestra) 8-15 -
Apenas momentos que passam na lista de verificação da rubrica contam. Nunca inclua clipes fracos para atingir um número.
picks.json (mínimo)
[{"id": "1", "start": 65.5, "end": 110.3, "title": "Toda inundação é causada pelas mudanças climáticas?",
"hook_start": 74.85, "hook_end": 80.1, "payoff_start": 102.0,
"why": "Afirmação inesperada primeiro, resolve no final.", "comment_bait": "Você sabia disso?",
"description": "...", "hashtags": ["#shorts", "#clima"],
"caption_overrides": [{"w": 219, "text": ""}, {"start": 90.1, "end": 92.4, "text": "palavras exatas aqui"}]}]
Obrigatório: id, start, end (segundos da fonte). hook_start/hook_end move uma linha de 2-3 s para
a frente ("hook_mode": "repeat" a mantém no corpo também). payoff_start coloca o som grave de impacto.
caption_overrides: {"w": N, "text": ""} edita/exclui a palavra N ((wN) em
transcript.txt, i em words.tsv); {"start", "end", "text"} substitui todas as palavras nesse intervalo.
Esquema completo e pontuação: references/viral-rubric.md.
Flags de renderização
| flag | efeito |
|---|---|
--fast | x264 ultrafast CRF 24, amostragem facial a 4 fps (pré-visualização). Padrão: preset faster, CRF 20 |
--only ID | renderiza uma escolha (repetível) |
| `--layout auto | crop |
--music FILE | faixa de música fornecida pelo usuário, cerca de 17 LU abaixo da voz, com ducking por compressão sidechain. --music-db 20 = mais silencioso |
--sfx-dir DIR | use seus próprios whoosh_fast, whoosh_soft, thud_low, pop, tick (.wav/.mp3/.flac/.ogg) em vez dos sintetizados |
--no-sfx, --no-silence-cut | desativa esses recursos |
--font "Lato Black", --font-size 84, `--highlight yellow | green, --no-upper` |
--preset, --crf, --keep-tmp | substituições do codificador; mantém wavs de voz/mix e captions.ass para depuração |
Ambiente: CLIPWISE_HOME (padrão ~/.clipwise), CLIPWISE_VENV, CLIPWISE_WORK,
CLIPWISE_MODEL (padrão large-v3-turbo), CLIPWISE_DEVICE (auto|cpu|cuda).
O que a renderização faz por escolha
Gancho movido para o início, silêncios > 0,35 s cortados (limiar dos próprios níveis de fala/ruído do clipe), partes mantidas ajustadas à grade de 30 fps para que as amostras de áudio igualem os quadros. Rastreamento facial com YuNet nos quadros que sobrevivem ao corte: rosto dominante, aderente (um novo rosto deve ser 1,6x maior por 1,2 s para assumir), câmera suave com zona morta, cortes apenas nas edições. Zoom 1.0/1.12 a cada 2-4 s. Legendas ASS palavra por palavra (máx. 4 palavras, palavra ativa destacada) colocadas abaixo do queixo e acima de y 1620. Limpeza de voz, SFX sintetizados, música opcional com ducking, duas passagens de loudnorm para -14 LUFS / -1.5 dBTP. H.264 + AAC 48 kHz, 1080x1920, 30 fps. As durações finais dos fluxos de A/V são garantidas.
Temporizações medidas (CPU de 2 núcleos, sem GPU)
| etapa | medido |
|---|---|
| busca: 85 MB 1080p VP9 web download + recodificação de janela de 3 min para H.264 | 7,7 min no total (download dominou, cerca de 5 min) |
| busca: clipe de 20 s 10-bit HDR do iPhone (mapeamento de tom + CFR) | 45 s (HDR custa cerca de 2,3x a duração) |
| transcrever large-v3-turbo, 3 min em inglês | 110 s ASR (0,61x tempo real) + 19 s carregamento do modelo |
| renderizar padrão, clipe de 40,6 s | 85 s |
renderizar --fast, clipe de 26,4 s / clipe pad de 17,1 s | 32 s / 30 s |
Armadilhas
- Muro de bot do YouTube ("Faça login para confirmar que você não é um robô"): intermitente, dependente de IP.
fetch sai com código 3. Peça ao usuário
--cookies cookies.txt(exportado do navegador dele) ou o próprio arquivo / um link do Drive ou Dropbox. Não faça loop sobre clientes player ou proxies do yt-dlp. Links privados do Drive saem com código 2: peça compartilhamento "qualquer pessoa com o link" ou um arquivo local. - Sincronia A/V é uma regra rígida. As durações dos fluxos de áudio e vídeo de cada saída devem corresponder
dentro de 0,1 s (renderização verifica). Nunca apare com cópia de fluxo em um início não zero, nunca
corte áudio com
aselect; use os scripts. - A receita de ASR é fixa: normalize o áudio primeiro, detecte automaticamente o idioma, sem VAD, sem
initial_prompt(vaza para a transcrição). Mantenha large-v3-turbo;smallentra em loop e alucina em fala com sotaque ou mista (transcrição avisa sobre loops). - Fala não inglesa pode voltar traduzida. Para muitos idiomas escritos em uma
escrita não latina (e para fala mista), o whisper retorna inglês. A transcrição então
é apenas um guia de tempo e significado: escreva as linhas de legenda no idioma original do falante
e escrita com intervalos
caption_overrides{"start", "end", "text"}, e mostre-as ao usuário antes de renderizar. Títulos e hashtags também seguem o idioma do falante. - Legendas: nunca sobre o rosto, e acima dos ~300 px inferiores (interface da plataforma). Se a
folha mostrar um conflito, encurte a escolha, use
--layout padou reduza--font-size. - O rastreador segue o maior rosto, não o falante. Para duas pessoas falando em uma
tomada ampla, use
--layout padou escolha uma janela onde apenas uma pessoa fala. - Redimensionamento: uma fonte 1080p 16:9 é cortada para 608x1080 e escalada 1.8x; fontes 720p são 2.7x e parecem suaves. Prefira downloads 1080p+.
- CPUs pequenas: nunca execute duas codificações, ou transcrição e uma codificação, ao mesmo tempo; renderize escolhas uma após a outra (run.py já faz isso).