Communitygithub.com

Easel clipify — 笑点切片→9:16 人脸平移

长英文口播找笑点切成 10–25 秒短片,可选 16:9→9:16 人脸平移/分屏,烧录 opus 逐词 ASS。含 scripts + assets/preview.png。隶属 1.6k★ ZJU-REAL/Easel 套件。

Easel clipify — 笑点切片→9:16 人脸平移 是什么?

Short-form Editing 步骤2(笑点/竖屏):ZJU-REAL Easel clipify — Whisper 找笑点→裁切→人脸硬切平移 9:16→opus 卡拉OK ASS。技能包自带 preview.png。承接 claude-shorts 候选变成静音信息流可播竖屏。

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

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Clipify

找到视频中最有趣的时刻,将它们剪切成独立的片段,可选将16:9格式转换为9:16(人脸跟踪或分屏),并添加类似Opus风格的逐词字幕。

输入

  • 视频文件路径(用户提供;否则询问)
  • 可选:要求的格式(9:16、16:9、1:1)——若未指定,在选定候选片段后询问
  • 可选:字幕样式偏好——若未指定,在添加字幕前询问

工具(仅使用最快路径)

  • Whisper: whisper --model tiny.en --word_timestamps True --output_format json(比small.en快约10倍;英文字幕质量足够)。对于非英语:--model base(省略--language)。
  • ffmpeg: 硬件解码为可选且平台相关——使用-hwaccel auto,或省略(macOS:videotoolbox;Linux:vaapi/cuda/无)。渲染时添加-preset ultrafast。最终母版使用-c:v libx264 -crf 20。
  • Numpy 用于音频对齐(FFT互相关)。无需scipy/cv2。
  • 脚本: <skill-dir>/scripts/(其中<skill-dir>是包含此SKILL.md的目录——通常为~/.claude/skills/clipify/)
    • analyze.py — 根据两个感兴趣区域(ROI)的运动文件生成发言人时间线
    • build_pan.py — 生成带硬切换的ffmpeg裁剪x表达式
    • build_ass.py — 从whisper JSON生成Opus风格ASS字幕
    • audio_align.py — 在较长源文件中查找子片段的偏移量

工作目录: /tmp/clipify/(开始时创建,保留工件用于调试)。


工作流

步骤 1——找到最有趣的部分

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

阅读生成的JSON(或.txt),挑选3–5个候选片段。需要扫描的有趣信号:

  • 笑点和反应: 类似“what”、“wait”、“no way”、笑声、“haha”、粗话等词语
  • 反转时刻: 铺垫问题 → 意想不到的答案
  • 尴尬停顿: Whisper片段中有长时间间隙,或填充词(“uh”、“um”)
  • 自嘲/可引用的金句: 短小独立的陈述句
  • 音频峰值: 通过ffmpeg -af volumedetect检测,或寻找快速来回对话(交替的短Whisper片段)

为每个候选片段提议:[起始时间,结束时间,为何有趣,建议标题]。目标片段时长10–25秒。列出清单,由用户确认/选择。

步骤 2——修剪每个选定的片段

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

(使用-c copy即时修剪。仅在需要帧精确裁剪时重新编码。)

步骤 3——决定输出格式

询问用户(如果他们已指定则跳过):“9:16(TikTok / Reels)、16:9(YouTube)还是1:1(Instagram Feed)?”

步骤 4——如果16:9 → 9:16:人脸跟踪还是分屏

用ffprobe检测源长宽比。如果源图像是16:9且目标是9:16,则询问:

“两个选项:(a) 硬切换跟踪 跟随说话者(一次只显示一张脸),或者 (b) 分屏堆叠 同时显示两张脸。您想要哪个?”

如果只有一张脸(单人说话片段),则跳过此问题。对于单人说话,仅居中裁剪。

步骤 4a——人脸跟踪(推荐用于快速切换的对话镜头)

  1. 定位两个脸部的感兴趣区域(ROI)。 采样一帧:ffmpeg -ss <中间时间> -i <片段> -frames:v 1 /tmp/clipify/probe.jpg。读取它。目测每个脸的嘴+下巴区域,以源图像的像素坐标x,y,w,h表示。(无需cv2——摄像机在片段内是静态的;一帧足够。)通过绘制框验证:

    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
    

    最多迭代两次。框应覆盖嘴+下巴,避免手部或麦克风。不要过度调整——帧差法容错性高。

  2. 提取每个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. 生成发言人时间线(最短驻留时间1.0秒——短插话合并到前一个发言人):

    python3 <skill-dir>/scripts/analyze.py /tmp/clipify/L.txt /tmp/clipify/R.txt 1.0 > /tmp/clipify/segments.json
    
  4. 为人脸跟踪选择裁剪的x坐标,从源图像中获取9:16垂直条。假设源宽度W=1920且目标宽度W=1080,裁剪条宽度=608。

    • LEFT_X = face_left_center_x - 304(限制≥0)
    • RIGHT_X = face_right_center_x - 304(限制≤ source_W - 608)
  5. 生成硬切换x表达式并渲染:

    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
    

    假设源为1920×1080;对于4K源,要么先缩小,要么将所有坐标加倍。

步骤 4b——分屏(两张脸始终可见)

两个堆叠的图块,每个1080×960。当前说话者的图块位于顶部——说话者变化时覆盖翻转。

[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]

从segments.json构建<RIGHT_SPEAKER_ENABLE>,在右侧说话者片段上使用between(t,a,b)+between(t,a,b)+...。图块裁剪应围绕每张脸约720×640(1.125:1以匹配1080×960)。

步骤 5——添加字幕

询问一次(仅当用户尚未指定样式时):

“三种字幕样式:opus(大而粗的白色文字,黄色活动词高亮)、karaoke(4词为一块,绿色高亮)、minimal(简洁Helvetica,无高亮)。或者粘贴您喜欢的示例。”

如果用户粘贴参考图像/示例:尽可能匹配字体、大小、粗细、颜色、位置和动画——自定义编写ASS文件或扩展build_ass.py。

否则使用预设:

# 在修剪后的片段上重新运行Whisper以获得相对于片段开始的准确时间戳
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

烧录字幕:

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"

步骤 6——交付

  • 将每个输出保存到<源目录>/clipify_out/(如果不存在则创建目录)
  • 每片段打印一行:名称、时长、有趣之处、输出路径
  • 打印第一个输出路径(或打开它——Linux xdg-open <路径>,macOS open <路径>)以便用户检查
  • 提供迭代选项(不同样式、不同ROI、切换到分屏、重新调整字幕时间)

陷阱(来自先前运行的经验——避免重复)

  • 不要过度调整ROI。 最多迭代两次。运动差分容错性高——覆盖嘴+下巴的较宽ROI即使不完全对准嘴部也能正常工作。
  • 注意片段内的场景切换。 运行ffmpeg -filter:v "select='gt(scene,0.3)',showinfo" -f null -以计数切换。如果16:9→9:16片段有许多切换,固定的人脸ROI仅对主要场景有效;警告用户,并提议要么选择单次拍摄的片段,要么接受在切换期间偏离中心的构图。
  • 源分辨率很重要。 如果源图像为4K,先缩小到1920×1080(更快,对于9:16输出足够),或者将所有ROI/跟踪坐标乘以2。
  • 源文件中已烧录字幕。 某些“原始”片段仍包含字幕。如果是这样,通过音频互相关(audio_align.py)找到无字幕的母版,并从那里修剪。
  • 如果短片段足够,不要在完整的长篇源文件上运行Whisper。 在步骤2之后对修剪后的片段运行Whisper;仅在步骤1中如果需要转录来找到有趣时刻时,才对完整源文件运行Whisper。
  • 用一句话陈述计划,然后行动。 不要叙述每一次迭代。

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 写具体某条视频的脚本。

相关技能