Communitygithub.com

Easel clipify — punchline→9:16 face-pan

Acha punchlines, corta 10–25s, reframe 16:9→9:16 face-pan/split, ASS opus. preview.png. Easel 1.6k★.

O que é Easel clipify — punchline→9:16 face-pan?

Short-form passo 2: Easel clipify. Punchlines→9:16. Depois de claude-shorts.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ZJU-REAL/Easel/tree/main/skills/openclaw/clipify

Perguntar na sua IA favorita

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

Documentação

Clipify

Encontre os momentos mais engraçados de um vídeo, corte-os como clipes independentes, opcionalmente reformate 16:9 → 9:16 (panorâmica de rosto ou tela dividida) e adicione legendas no estilo Opus palavra por palavra.

Entradas

  • Um caminho de arquivo de vídeo (o usuário fornecerá; caso contrário, pergunte)
  • Opcional: formato solicitado (9:16, 16:9, 1:1) — se não fornecido, pergunte após os candidatos serem escolhidos
  • Opcional: preferência de estilo de legenda — se não fornecido, pergunte antes de adicionar legendas

Ferramentas (use apenas o caminho mais rápido)

  • Whisper: whisper --model tiny.en --word_timestamps True --output_format json (≈10× mais rápido que small.en; qualidade suficiente para inglês). Para não inglês: --model base (remova --language).
  • ffmpeg: a decodificação por hardware é opcional e específica da plataforma — use -hwaccel auto ou omita (macOS: videotoolbox; Linux: vaapi/cuda/nenhum). Adicione -preset ultrafast para renderizações. Use -c:v libx264 -crf 20 para o mestre final.
  • Numpy para alinhamento de áudio (correlação cruzada FFT). Sem necessidade de scipy/cv2.
  • Scripts: <skill-dir>/scripts/ (onde <skill-dir> é o diretório que contém este SKILL.md — tipicamente ~/.claude/skills/clipify/)
    • analyze.py — linha do tempo do locutor a partir de dois arquivos de movimento ROI
    • build_pan.py — expressão x de corte ffmpeg com cortes secos
    • build_ass.py — legendas ASS no estilo opus a partir do JSON do whisper
    • audio_align.py — encontra o deslocamento de um subclipe em uma fonte mais longa

Diretório de trabalho: /tmp/clipify/ (crie no início, deixe artefatos para depuração).


Fluxo de Trabalho

Etapa 1 — Encontre as partes mais engraçadas

mkdir -p /tmp/clipify
ffmpeg -y -i "$VIDEO" -vn -ac 1 -ar 16000 /tmp/clipify/audio.wav
whisper /tmp/clipify/audio.wav --model tiny.en --word_timestamps True --output_format json --output_dir /tmp/clipify --language en

Leia o JSON resultante (ou .txt) e escolha 3–5 clipes candidatos. Sinais engraçados a procurar:

  • Punchlines e reações: palavras como "what", "wait", "no way", risadas, "haha", xingamentos
  • Momentos de virada: pergunta de configuração → resposta inesperada
  • Pausas estranhas: segmento do Whisper com longo intervalo, ou preenchimento ("uh", "um")
  • Autodepreciação / frases citáveis: frases declarativas curtas que se sustentam sozinhas
  • Picos de áudio: detecte via ffmpeg -af volumedetect ou procure por idas e vindas rápidas (segmentos curtos alternados do Whisper)

Para cada candidato, proponha: [início, fim, por que é engraçado, título sugerido]. Mire em clipes de 10–25s. Mostre a lista e deixe o usuário confirmar/escolher.

Etapa 2 — Corte cada clipe escolhido

ffmpeg -y -ss "$START" -t "$DURATION" -i "$VIDEO" -c copy /tmp/clipify/clip_$N.mp4

(Use -c copy para corte instantâneo. Re-codifique apenas se os cortes precisarem ser precisos por quadro.)

Etapa 3 — Decida o formato de saída

Pergunte ao usuário (pule se já especificado): "9:16 (TikTok / Reels), 16:9 (YouTube), ou 1:1 (feed do Insta)?"

Etapa 4 — Se 16:9 → 9:16: panorâmica entre rostos vs tela dividida

Detecte a proporção de origem com ffprobe. Se a origem for 16:9 e o destino for 9:16, pergunte:

"Duas opções: (a) panorâmica de corte seco que segue quem está falando (um rosto na tela por vez), ou (b) tela dividida empilhada com ambos os rostos visíveis. Qual você quer?"

Pule a pergunta se houver apenas um rosto (clipe de um único locutor). Para um único locutor, basta cortar centralizado.

Etapa 4a — Panorâmica entre rostos (recomendado para diálogo de cabeça falante com cortes rápidos)

  1. Localize as duas ROIs de rosto. Amostre um quadro: ffmpeg -ss <meio> -i <clipe> -frames:v 1 /tmp/clipify/probe.jpg. Leia-o. Determine a área da boca+queixo de cada rosto como x,y,w,h no espaço de pixels da origem. (Não é necessário cv2 — a câmera é estática dentro de um clipe; um quadro é suficiente.) Verifique desenhando caixas:

    ffmpeg -i probe.jpg -vf "drawbox=x=$LX:y=$LY:w=$LW:h=$LH:[email protected]:t=4,drawbox=x=$RX:y=$RY:w=$RW:h=$RH:[email protected]:t=4" verify.jpg
    

    Itere no máximo duas vezes. As caixas devem cobrir boca + queixo e evitar mãos/microfones. Não ajuste demais — a diferença de quadros é tolerante.

  2. Extraia a energia de movimento por quadro em cada ROI:

    ffmpeg -y -i clip.mp4 -filter_complex "
    [0:v]split=2[a][b];
    [a]crop=$LW:$LH:$LX:$LY,format=gray,tblend=all_mode=difference,signalstats,metadata=mode=print:key=lavfi.signalstats.YAVG:file=/tmp/clipify/L.txt[la];
    [b]crop=$RW:$RH:$RX:$RY,format=gray,tblend=all_mode=difference,signalstats,metadata=mode=print:key=lavfi.signalstats.YAVG:file=/tmp/clipify/R.txt[ra]
    " -map "[la]" -f null - -map "[ra]" -f null -
    
  3. Construa a linha do tempo do locutor (permanência mínima de 1.0s — interjeições curtas são mescladas ao locutor anterior):

    python3 <skill-dir>/scripts/analyze.py /tmp/clipify/L.txt /tmp/clipify/R.txt 1.0 > /tmp/clipify/segments.json
    
  4. Escolha coordenadas x da panorâmica para uma faixa vertical 9:16 a partir da origem. Com origem W=1920 e destino W=1080, largura da faixa de corte = 608.

    • LEFT_X = face_left_center_x - 304 (limite ≥ 0)
    • RIGHT_X = face_right_center_x - 304 (limite ≤ source_W - 608)
  5. Gere a expressão x de corte seco e renderize:

    EXPR=$(python3 <skill-dir>/scripts/build_pan.py /tmp/clipify/segments.json $LEFT_X $RIGHT_X)
    ffmpeg -y -i clip.mp4 -filter_complex \
      "[0:v]crop=608:1080:x='$EXPR':y=0,scale=1080:1920:flags=lanczos[v]" \
      -map "[v]" -map 0:a -c:v libx264 -preset fast -crf 20 -pix_fmt yuv420p \
      -c:a aac -b:a 192k /tmp/clipify/clip_panned.mp4
    

    Origem 1920×1080 presumida; para origem 4K, reduza a resolução primeiro ou dobre todas as coordenadas.

Etapa 4b — Tela dividida (ambos os rostos sempre visíveis)

Duas colunas empilhadas, 1080×960 cada. O rosto do locutor ativo fica em cima — a sobreposição alterna nas mudanças de locutor.

[0:v]split=2[a0][a1];
[a0]crop=Wcrop:Hcrop:LX_tile:LY_tile,scale=1080:960,split=2[lt0][lt1];
[a1]crop=Wcrop:Hcrop:RX_tile:RY_tile,scale=1080:960,split=2[rt0][rt1];
[lt0][rt0]vstack[layoutL];
[rt1][lt1]vstack[layoutR];
[layoutL][layoutR]overlay=0:0:enable='<RIGHT_SPEAKER_ENABLE>'[v]

Construa <RIGHT_SPEAKER_ENABLE> a partir de segments.json como between(t,a,b)+between(t,a,b)+... sobre os segmentos do locutor direito. Os cortes das colunas devem segmentar ~720×640 ao redor de cada rosto (1.125:1 para corresponder a 1080×960).

Etapa 5 — Adicione legendas

Pergunte uma vez (apenas se o usuário não especificou um estilo):

"Três estilos de legenda: opus (branco grande e negrito, destaque amarelo na palavra ativa), karaokê (blocos de 4 palavras, destaque verde), minimal (Helvetica limpa, sem destaque). Ou cole um exemplo que você goste."

Se colarem uma imagem de referência/exemplo: corresponda a fonte, tamanho, peso, cor, posição e animação o mais próximo possível — escreva um ASS personalizado manualmente ou estenda build_ass.py.

Caso contrário, use o predefinido:

# Re-execute whisper no clipe cortado para timestamps precisos relativos ao início do clipe
whisper /tmp/clipify/clip_panned.mp4 --model tiny.en --word_timestamps True --output_format json --output_dir /tmp/clipify --language en
python3 <skill-dir>/scripts/build_ass.py /tmp/clipify/clip_panned.json /tmp/clipify/captions.ass opus

Grave as legendas:

ffmpeg -y -i /tmp/clipify/clip_panned.mp4 -vf "subtitles=/tmp/clipify/captions.ass" \
  -c:v libx264 -preset fast -crf 20 -c:a copy "$OUTPUT.mp4"

Etapa 6 — Entregue

  • Salve cada saída em <source_dir>/clipify_out/ (crie o diretório se não existir)
  • Imprima uma linha por clipe: nome, duração, o que era engraçado, caminho da saída
  • Imprima o primeiro caminho de saída (ou abra-o — Linux xdg-open <caminho>, macOS open <caminho>) para que o usuário possa verificá-lo
  • Ofereça-se para iterar (estilo diferente, ROI diferente, trocar para tela dividida, reajustar tempo das legendas)

Armadilhas (lições de execuções anteriores — não repita)

  • Não ajuste demais as ROIs. No máximo duas iterações. A diferença de movimento é tolerante — ROIs mais largas cobrindo boca+queixo funcionam bem mesmo se não perfeitamente centradas na boca.
  • Cuidado com cortes de cena dentro de um clipe. Execute ffmpeg -filter:v "select='gt(scene,0.3)',showinfo" -f null - para contar os cortes. Se um clipe 16:9→9:16 tiver muitos cortes, as ROIs fixas de rosto funcionam apenas para a cena dominante; avise o usuário e ofereça-se para escolher um clipe de uma única tomada ou aceitar enquadramento descentralizado durante os cortes.
  • A resolução da origem importa. Se a origem for 4K, reduza a resolução para 1920×1080 primeiro (mais rápido, bom para saída 9:16) ou multiplique todas as coordenadas ROI/panorâmica por 2.
  • Legendas queimadas na origem. Alguns clipes "brutos" ainda têm legendas. Nesse caso, encontre o mestre sem legendas via correlação cruzada de áudio (audio_align.py) e corte a partir dele.
  • Não execute whisper na fonte completa se um clipe curto for suficiente. Execute whisper no clipe cortado após a Etapa 2; execute whisper na fonte completa na Etapa 1 apenas se precisar de uma transcrição para encontrar momentos engraçados.
  • Declare o plano em uma linha, depois aja. Não narre cada iteração.

Individual skills in this repo

This repo contains 9 individual skills — each has its own dedicated page.

ZJU-REAL/Easel

AI 视频生成:文生视频 / 图生视频 / 数字人首帧驱动。通过可插拔 provider(通义万相 Wan / 火山 Seedance / 快手可灵 / OpenAI 兼容)异步生成视频,用户自备 API key。当用户说 AI 视频生成、文生视频、图生视频、AI 生成视频、AI 短视频、让图片动起来、数字人视频、生成一段视频 时使用。与 video-strategy(选型/策略)、video-editing(剪辑处理)、clipify(切片)区别:本 SKILL 是从 0 用 AI 生成新视频。

ZJU-REAL/Easel

通用音频处理:音频剪辑/裁剪、格式转码(mp3/wav/m4a/aac)、音量归一化、从视频提取音轨、多段拼接、淡入淡出、变速(保音高)。当用户说“剪音频”“裁一段”“转成 mp3”“调音量/响度”“提取音轨/扒音频”“拼接音频”“淡入淡出”“加速/减速音频”“变速不变调”时使用。与 audio-denoise 的区别:audio-denoise 专做降噪,audio-editing 做除降噪外的通用音频操作(也内置 denoise 作为兜底)。

ZJU-REAL/Easel

一句话主题 → 成品短视频:自动串联 文案→配图/AI视频→配音→字幕→BGM→合成,把 Easel 制作层零件编排成一条'一键出片'流水线。**单条视频、口播/资讯向,画面默认逐句配图 + Ken Burns 缓动,需要动态时才逐段图生视频**。当用户说 一键生成视频、自动做短视频、主题生成视频、帮我做条视频、口播视频一条龙、自动出片、短视频一键生成 时使用。**有剧情/角色/对白/反转/多集的短剧改用 short-drama(每镜强制图生视频、不用静态图冒充);只写脚本用 video-script;只生成单个片段用 ai-video-gen。**

ZJU-REAL/Easel

自动字幕 / 语音转字幕:把音频或视频里的语音识别成字幕文件(SRT/ASS/TXT/JSON),可选把字幕烧录进视频。当用户说自动字幕、语音转字幕、视频加字幕、上字幕、转录、听写、字幕文件、生成字幕、烧字幕时使用。

ZJU-REAL/Easel

音乐卡点视频 / 踩点视频:检测背景音乐的节拍,让图片或片段在节拍点上切换,配推进/白闪特效,做出燃系'卡点'短视频。当用户说 卡点视频、踩点视频、音乐卡点、节奏卡点、按音乐切换、鼓点视频、踩节奏、beat 卡点、图片卡点、卡点混剪 时使用。基于 shared/scripts/beatsync.py(librosa 节拍检测)。与 slideshow-video 区别:slideshow 每图固定时长、柔和转场,本 SKILL 切换点由音乐节拍决定、硬切踩点带特效。

ZJU-REAL/Easel

>- 通用图像处理加工:改尺寸/缩放、裁剪、补边适配平台尺寸、格式转换(png/jpg/webp)、 压缩到目标大小、加文字或图片水印、圆角、多图拼接、生成缩略图、读图片信息。 基于 image_ops.py 确定性处理。 使用时机:用户说"改尺寸"、"缩放图片"、"裁剪"、"压缩图片"、"加水印"、"转格式"、 "圆角"、"拼图/多图联排"、"缩略图"、"适配小红书/朋友圈尺寸"、"把图 pad 成 1:1"。 和 card-*(卡片类)的区别:card-* 是"HTML 设计→渲染出图", image-editing 只加工已有图片,不负责视觉设计。

ZJU-REAL/Easel

多角色对话配音:按 cast 和逐行对白为不同角色分配音色与情绪,合成多声线音轨和带角色名字幕。 当用户说“多角色/双人/剧本/对话配音、多人对白、不同角色不同声音、有声剧配音”时使用。 单一公共音色用 tts-voiceover;克隆本人音色用 voice-clone;整部短剧制作由 short-drama 编排。

ZJU-REAL/Easel

Easel video-highlights: CN/livestream highlight extract + stable static vertical reframe (sibling to clipify).

ZJU-REAL/Easel

>- 视频制作策略与工具选型:AI 视频生成模型对比、视频脚本结构设计、制作流程规划,覆盖产品演示/解说/社媒短视频场景。 当用户说"视频怎么做""视频选型""用什么工具做视频""视频制作流程""视频策略""视频系列规划"时使用。 和 video-script 的区别:video-strategy 做内容规划与工具选型,video-script 写具体某条视频的脚本。

Habilidades Relacionadas