Adicionar a introdução e a conclusão
As vinhetas são MP4s curtos com seu próprio jingle, um par por orientação, listados nas preferências. Esta skill normaliza tudo para um formato, junta introdução, vídeo e conclusão com cross-fades curtos (vídeo e áudio) e renderiza o resultado.
Preferências
remote-video-editing/preferences.json (ordem de busca como em clean-voice-sidon):
| Chave | Significado |
|---|---|
stings | {"intro_16x9": url, "outro_16x9": url, "intro_9x16": url, "outro_9x16": url}; URLs ou caminhos locais |
sting_fade_s | Duração do cross-fade, padrão 0.5 |
render_notes | Onde executar codificações longas (ex.: um servidor em vez de um laptop). Siga-as. |
Se stings não estiver definido, pergunte pelos arquivos. O plugin não inclui nenhum ativo da marca.
Orientação
Leia a orientação exibida, não o tamanho codificado: celulares armazenam vídeo retrato como 1920x1080 com uma tag
de rotação. Verifique com
ffprobe -v error -select_streams v:0 -show_entries stream=width,height:stream_side_data=rotation -of compact IN.
Uma rotação de 90 ou -90 troca largura e altura. O ffmpeg aplica a rotação automaticamente ao decodificar.
- Vídeo retrato (9:16): use
intro_9x16/outro_9x16, canvas 1080x1920. - Paisagem: use o par 16:9, canvas 1920x1080.
- Versão 16:9 de um vídeo retrato (para o feed principal do YouTube): canvas 1920x1080, o vídeo redimensionado para 1080 de altura no centro, sobre uma cópia desfocada, escurecida e ampliada de si mesmo; use as vinhetas 16:9. A cadeia
[v1]abaixo torna-se:
Teste em um corte de 8 segundos ([1:v]fps=30,split[a][b]; [a]scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080,scale=480:270,boxblur=20:2,scale=1920:1080,eq=brightness=-0.06:saturation=0.9[bg]; [b]scale=-2:1080[fg];[bg][fg]overlay=(W-w)/2:0,setsar=1,format=yuv420p[v1]-ss 60 -t 8) e mostre um quadro antes de renderizar o vídeo inteiro.
Renderização
W:H é o canvas, F o fade (0.5), DI a duração da introdução, DV a duração do vídeo (ffprobe format=duration).
Offsets: primeiro fade em DI-F; segundo em DI+DV-2*F.
ffmpeg -y -i intro.mp4 -i main.mp4 -i outro.mp4 -filter_complex "
[0:v]fps=30,scale=W:H,setsar=1,format=yuv420p[v0];
[1:v]fps=30,scale=W:H:force_original_aspect_ratio=decrease,pad=W:H:(ow-iw)/2:(oh-ih)/2,setsar=1,format=yuv420p[v1];
[2:v]fps=30,scale=W:H,setsar=1,format=yuv420p[v2];
[0:a]aresample=48000,aformat=channel_layouts=stereo[a0];
[1:a]aresample=48000,aformat=channel_layouts=stereo[a1];
[2:a]aresample=48000,aformat=channel_layouts=stereo[a2];
[v0][v1]xfade=transition=fade:duration=F:offset=DI-F[v01];
[v01][v2]xfade=transition=fade:duration=F:offset=DI+DV-2*F[v];
[a0][a1]acrossfade=d=F[a01];[a01][a2]acrossfade=d=F[a]" \
-map "[v]" -map "[a]" -c:v libx264 -preset medium -crf 20 -maxrate 10M -bufsize 20M -c:a aac -b:a 192k -movflags +faststart out.mp4
- Vários clipes de origem: junte-os primeiro (mesmo padrão de filtro, ou o demuxer concat se compartilharem codec), depois
trate o resultado como
main.mp4. - Isso é uma recodificação completa: minutos de cada núcleo para um vídeo de 10 minutos em 1080p. Execute no Modal, não localmente e
não em um servidor doméstico: coloque os argumentos após as entradas (de
-filter_complexa+faststart) um por linha emrender.args, depois$MODAL run "${CLAUDE_PLUGIN_ROOT}/scripts/ffmpeg_modal.py" --inputs intro.mp4,main.mp4,outro.mp4 --args-file render.args --out out.mp4(modal_commanderun_notesdas preferências dizem onde o Modal é executado). Junte vários clipes no mesmo gráfico (filtroconcat) em vez de uma etapa separada. Exclua a pasta do job no volumevideo-editing-workdepois. - xfade precisa que ambas as entradas estejam na mesma base de tempo: coloque
fps=30,settb=1/30em cada ramo de vídeo (inclusive após umconcat), ou o ffmpeg falha com "First input link main timebase (1/30) do not match". - Taxa de bits: mantenha o limite (
-crf 20 -maxrate 10M -bufsize 20M). CRF 18 puro em vídeos de celular ruidosos resultou em 24 Mbps, cerca de 2 GB para 11 minutos (13/11/2026). O YouTube recodifica de qualquer maneira e sugere 8-12 Mbps para uploads 1080p. - Verifique: a duração da saída é aproximadamente
DI + DV + DO - 2*F, e verifique os quadros emDI-F/2(meio do fade), no meio e no final.
Filmagem à mão: estabilizar na mesma renderização
Vídeos de celular gravados à mão se beneficiam de estabilização suave (o usuário, 13/11/2026, após a primeira atualização do final de semana de Hebrish ter sido lançada sem ela). Use o vid.stab do ffmpeg (libvidstab; o ffmpeg do Debian, que a imagem Modal instala,
tem; verifique com ffmpeg -filters | grep vidstab). Duas passagens, ambas no Modal:
- Detectar (rápido, apenas análise, escreve um arquivo de transformações), por clipe de origem:
ffmpeg -i main.mp4 -vf vidstabdetect=shakiness=5:accuracy=15:result=main.trf -f null -Execute como seu próprio jobffmpeg_modal.py(args-vf/vidstabdetect=...:result=/work/<job>/main.trf/-f/null, saída-), ou adicione uma etapa de detecção ao script. O arquivo.trfdeve ficar ao lado da entrada no volume. - Transformar dentro da renderização principal, primeiro nesse ramo de vídeo do clipe, antes de correção de cor e redimensionamento:
vidstabtransform=input=main.trf:smoothing=20:zoom=2:optzoom=0,unsharp=5:5:0.4smoothingem torno de 15-30 (quadros) mantém o movimento natural; umzoom=2fixo (porcentagem) esconde as bordas móveis sem o bombeamento queoptzoom=1causa em uma cabeça falante. O unsharp suave compensa a suavidade da reamostragem.
Teste em um corte de 8 segundos primeiro e compare uma imagem estática e um clipe curto com o usuário antes da renderização final. Se
libvidstab estiver faltando, deshake é uma alternativa de uma passagem (mais fraca). Estabilizadores de IA não são necessários para isso.
Criando vinhetas
As vinhetas em uso foram renderizadas a partir dos SVGs da marca com um pequeno script Pillow mais um jingle gerado. Encontre-o
com find-script (tags logo, sting, intro), e não regere o logotipo com um modelo de vídeo: modelos de vídeo
distorcem as formas das letras.