Communitygithub.com

Easel clipify — 笑點切片→9:16 人臉平移

長英文口播找笑點切短片,可選 16:9→9:16 人臉平移/分割,燒錄 opus 逐詞 ASS。含 preview.png。1.6k★ Easel。

Easel clipify — 笑點切片→9:16 人臉平移 是什麼?

短影音步驟2:Easel clipify。笑點→豎屏→opus ASS。承接 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 個候選片段。要掃描的有趣訊號:

  • 笑點與反應: 如「什麼」、「等等」、「不會吧」、笑聲、「哈哈」、髒話
  • 反轉時刻: 設定問題 → 意想不到的回答
  • 尷尬停頓: Whisper 片段中有長間隔,或填充詞(「呃」、「嗯」)
  • 自嘲 / 可引用的名言: 簡短陳述句,可獨立存在
  • 音頻高峰: 透過 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(Insta 貼文)?」

步驟 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. 為來源的 9:16 垂直條帶選擇平移 x 座標。 假設來源寬度 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 來源,則先降級至 1920×1080 或將所有座標加倍。

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

相關技能