Communitygithub.com

huzaifa-hb/video-edit

透過對話編輯真實影片,完全本機運行。使用 whisper.cpp 進行轉錄、從轉錄稿挑選鏡頭、撰寫 JSON 編輯清單、驗證、以 ffmpeg 渲染、加入 Hyperframes 動態字幕與疊加層、重新構圖為 9:16 / 1:1 / 16:9,最後自我檢查渲染結果。適用於談話性影片、UGC 與見證廣告、創始人影片、通話錄音、訪談、教學等場景。

video-edit 是什麼?

這是一個功能完整的 AI 影片編輯技能,專為需要在單一影片檔案內進行精確切割、修剪、字幕添加、重新構圖或製作多種廣告變體的使用者設計。其核心原理是「以音訊為優先,視覺為輔」:AI 首先透過本機 whisper.cpp 對影片進行逐字轉錄,保留填充詞(如「嗯」、「啊」),並以短語為單位打包成文字稿。隨後,AI 會與使用者對話,了解影片類型、目標長度、風格偏好等,然後根據文字稿中的詞邊界與靜音間隙,自動生成 JSON 編輯決策清單(EDL)。此技能的一大特色是嚴格的多階段驗證流程:在每次渲染前,`validate_edl.py` 會檢查 EDL 中的來源 ID、時間範圍、切割位置(確保不從詞中間切開)、疊加層檔案是否存在等,並可自動修正邊界問題。渲染後,AI 會對輸出進行自我評估(包括視覺連續性、音量一致性、字幕可讀性等),必要時還會召喚一個「評論子代理」來挑錯。此技能完全本機執行,無需 API 金鑰,支援 macOS (Homebrew) 與 Linux,並能處理單一或多位說話者(如訪談、通話錄音)。其內建 Hyperframes 引擎可產生具動畫效果的字幕層,而非傳統燒錄字幕,並且支援動態重新構圖(如將橫向影片轉為直向),使其非常適合製作社群媒體廣告素材。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add huzaifa-hb/video-edit

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Video Edit

Fork 自 browser-use/video-use (MIT):使用本機 whisper.cpp 取代 ElevenLabs、在每次渲染前加入驗證關卡、使用 Hyperframes 字幕取代 libass 字幕、並加入畫布重新構圖功能以製作社群廣告變體。

原則

  1. LLM 從原始轉錄稿與隨需視覺資料進行推理。 唯一值得保留的衍生產物是打包過的短語層級轉錄稿 (takes_packed.md)。其他一切——填充詞標記、重拍偵測、鏡頭分類、重點評分——都在決策時才推導。
  2. 音訊優先,視覺後至。 剪輯候選點來自語音邊界與靜音間隙。只在決策點才深入檢視視覺資料。
  3. 提問 → 確認 → 執行 → 疊代 → 持久化。 在使用者以白話文確認策略之前,絕不動手剪輯。
  4. 一般化。 不要預設這是哪種影片。觀察素材,詢問使用者,然後才進行編輯。
  5. 藝術自由是預設值。 本文檔中的每個特定數值、預設集、字型、顏色、持續時間、音高結構與技術,都是來自一個已驗證影片的實際範例,而非強制規定。閱讀它們以了解可能性和為什麼有效。然後根據素材的實際情況和使用者的實際需求,做出你自己的品味判斷。你必須做的唯一事情在下方「硬性規則」中。 其他一切都是你的自由。
  6. 自由發明。 如果素材需要此處未描述的技術——分割畫面、畫中畫、下方身份卡、反應剪輯、速度坡道、凍結幀、交叉淡化、匹配剪輯、L-cut、J-cut、呼吸處的速度坡道等——儘管建立。輔助工具是 ffmpeg 和 PIL。它們能做到格式支援的任何事。無需等待許可。
  7. 在向使用者展示之前,先驗證自己的輸出。 如果你自己都不會發布,就不要呈現出來。

硬性規則(生產正確性——不可協商)

這些是偏離會導致靜默失敗或損壞輸出的部分。它們關乎正確性,而非品味。請記住它們。

  1. 字幕在濾鏡鏈中最後應用,在任何疊加層之後。否則疊加層會遮蓋字幕。靜默失敗。
  2. 逐片段提取 → 無損 -c copy 串接,而非單次濾鏡圖。否則在加入疊加層時會對每個片段進行兩次編碼。
  3. 在每個片段邊界加入 30ms 音訊淡化(afade=t=in:st=0:d=0.03,afade=t=out:st={dur-0.03}:d=0.03)。否則每次剪輯都會有可聽到的爆音。
  4. 疊加層使用 setpts=PTS-STARTPTS+T/TB 將疊加層的影格 0 移至其視窗起點。否則在疊加層視窗期間會看到動畫的中間部分。
  5. 字幕使用輸出時間軸偏移:output_time = word.start - segment_start + segment_offset,其中每個片段佔據其整個影格長度(captions.py 會處理這個)。否則字幕在片段串接後會錯位。
  6. 絕不在詞中間剪輯。 將每個剪輯邊緣對齊轉錄稿中的詞邊界。validate_edl.py --fix 會機械性地完成此操作。
  7. 為每個剪輯邊緣添加邊距。 工作範圍:30–200ms。詞邊緣已對齊音訊包絡,但邊距吸收了剩餘的誤差。快節奏時用較緊的邊距,電影感時用較鬆的。
  8. 僅使用逐詞原文 ASR。 絕不使用 SRT/短語模式(會失去亞秒級間隙資料)。絕不使用標準化填充詞(會失去編輯訊號)。transcribe.py 會提示 whisper 保留「um」/「uh」——不要移除這個提示。
  9. 每個來源快取轉錄稿。 除非原始檔案本身變更,否則絕不重新轉錄。
  10. 多個動畫使用平行子代理。 絕不循序執行。透過 Agent 工具同時生成 N 個;總耗時 ≈ 最慢的那個。
  11. 在執行前先確認策略。 在使用者批准白話文計劃之前,絕不動手剪輯。
  12. 所有階段輸出都在 <videos_dir>/edit/ 中。 絕不在技能目錄內寫入。
  13. 在每次渲染前進行驗證。 validate_edl.py <edl> --fix,只在退出碼為 0 時才渲染。它能捕捉到虛構的來源 ID、超出檔案結尾的時間、詞中間的剪輯、缺少疊加層檔案以及疊加層超出剪輯範圍——這些正是 LLM 撰寫的編輯清單會有的失敗模式。
  14. 字幕是 Hyperframes 圖層,而非燒錄字幕。 Homebrew 的 ffmpeg 沒有 libass,因此在 EDL 中使用 subtitles 會失敗。請使用 captions.py;render.py 會將字幕 WebM 合成到每個疊加層之上。
  15. 來源 ID 是檔案的主檔名。 在 sources 中,鍵必須是影片檔案名稱去掉副檔名(例如 take_B.mp4 對應 take_B),或在使用 --audio-track N 轉錄時為 <stem>.track<N>——轉錄稿就是這樣找到的。當字幕開啟時,驗證器會在不匹配時報錯。
  16. 每次渲染單一影格率。 如果你傳遞 --fps 給 render.py,也請將相同的 --fps 傳遞給 validate_edl.py 和 captions.py。範圍會被四捨五入到整數影格,使字幕永不偏移。

本文檔中的其他內容都是實際範例。每當素材需要時,請偏離這些範例。

目錄結構

技能位於自己的目錄中(輔助工具與範本在此檔案旁)。使用者影片放在他們指定的任何位置。所有階段輸出都進入 <videos_dir>/edit/。

<videos_dir>/
├── <來源檔案,保持不變>
└── edit/
    ├── project.md              ← 記憶;每次階段後追加
    ├── takes_packed.md         ← 短語層級轉錄稿,LLM 的主要閱讀視圖
    ├── edl.json                ← 剪輯決策(對於變體:edl_9x16.json, edl_1x1.json …)
    ├── transcripts/<name>.json ← 快取的 whisper.cpp 轉錄稿(逐詞 + 靜音)
    ├── captions_<edl stem>/    ← Hyperframes 字幕合成 + captions.webm
    ├── animations/slot_<id>/   ← 每個動畫的來源 + 渲染 + 推理
    ├── clips_graded/           ← 每個片段的提取(含調色 + 淡化)
    ├── downloads/              ← yt-dlp 輸出
    ├── verify/                 ← 除錯影格 / 時間軸 PNG
    ├── preview.mp4
    └── final.mp4

設定

install.sh / setup.sh 會安裝所有項目(Homebrew 套件、.venv、whisper 模型、Hyperframes + Chrome)。在冷啟動時僅需驗證——如果缺少 .venv 或某個輔助工具因匯入或缺少工具而失敗,請在執行任何其他操作之前執行 <此技能目錄>/setup.sh(它是冪等的):

  • PY=<此技能目錄>/.venv/bin/python 存在。使用 $PY 執行每個輔助工具,絕不使用系統 python(它缺少 numpy/Pillow/OpenCV)。
  • ffmpeg、ffprobe、whisper-cli 在 PATH 中,並有一個 ggml whisper 模型。預設值:~/.claude-video-vision/models/ggml-large-v3-turbo.bin;可透過 VIDEO_EDIT_WHISPER_MODEL 覆蓋。
  • Node.js 22+ 用於 Hyperframes。始終使用固定版本來呼叫:npx --yes [email protected] …。
  • yt-dlp 和 Manim 僅在首次使用時需要。此技能內含 skills/manim-video/;在建立 Manim slot 時請閱讀其 SKILL.md。
  • 無需 API 金鑰。除了 Hyperframes 的一次性 npm 下載外,沒有任何東西離開機器。

輔助工具位於此 SKILL.md 旁的 helpers/ 中。請根據包含此檔案的目錄解析其路徑。

輔助工具

所有工具都以 $PY helpers/<name>.py … 的方式執行。

  • transcribe.py <video> — 本機 whisper.cpp,逐詞,保留填充詞,詞邊緣對齊音訊包絡,列出靜音。每個來源會快取(僅當檔案變更時才重新執行)。--language en 跳過語言偵測;--audio-track N 用於多音軌錄影。
  • transcribe_batch.py <videos_dir> — 資料夾中的每個影片,依序處理(whisper 已讓 GPU 飽和)。
  • pack_transcripts.py --edit-dir <dir> — transcripts/*.json → takes_packed.md(短語層級,在靜音 ≥ 0.5s 處斷開;對於語速快的人,可將 --silence-threshold 降至 0.3)。
  • timeline_view.py <video> <start> <end> — 產生包含膠片條和波形的 PNG。隨需的視覺深入檢視工具。不是掃描工具——在決策點使用它,而非持續使用。
  • validate_edl.py <edl.json> [--fix] — 每次渲染前的關卡(硬性規則 13)。--fix 會將邊緣對齊到詞間隙、加入邊距(--pad-in、--pad-out)、將範圍四捨五入到整數影格、重新計算 total_duration_s、保留 edl.json.bak。關於邊緣附近少於 30ms 靜音的警告會通過 --fix:那些剪輯位於詞與詞接觸的位置——請將它們移動到真正的停頓處。
  • captions.py <edl.json> — 輸出時間軸的逐詞字幕,作為 Hyperframes 合成 → 透明的 captions.webm,設定 EDL 的 captions 鍵。樣式標誌:--accent、--color、--top、--size、--font、--case、--words、--no-pop。
  • render.py <edl.json> -o <out> — 逐片段提取(影格精確、HDR→SDR、畫布重新構圖、調色、淡化)→ 無損串接 → 疊加層(PTS 偏移)→ 字幕 → loudnorm。--preview 用於品質檢查,--draft 僅用於剪輯檢查。
  • reframe.py <edl.json> [--apply] — 跨每個範圍的 OpenCV 臉部偵測(YuNet)→ crop_x/crop_y,在 EDL canvas 上保持說話者居中並留有頭頂空間。每當 canvas 改變長寬比時,在執行 validate_edl.py --fix 後執行此工具。它會標記那些臉部 MOVES 過多以至於無法使用一個靜態裁剪的範圍(應將其分割),以及那些 no face 的範圍(請自行選擇裁剪)。某個範圍上的 "crop_lock": true 可保護手動裁剪。
  • scenes.py <video> — OpenCV 鏡頭變換偵測,加上每個鏡頭的 DARK / BLURRY 標記 → edit/shots/<stem>.json。當轉錄稿無法結構化腳本時使用:B-roll、產品鏡頭、蒙太奇、多機位輸出、無聲片段。鏡頭邊界是乾淨的視覺剪輯點;標記過的鏡頭在廣告中很少可用。
  • grade.py <in> -o <out> — ffmpeg 濾鏡鏈調色。預設集 + --filter '<raw>' 用於自訂。

對於動畫,建立 <edit>/animations/slot_<id>/ 並使用 Bash,然後透過 Agent 工具生成一個子代理。

流程

  1. 盤點。 對每個來源執行 ffprobe。對目錄執行 transcribe_batch.py。對於語音很少或沒有語音的來源(B-roll、產品鏡頭),改為執行 scenes.py 以取得其鏡頭。閱讀其輸出的 QC: 行(也在每個轉錄稿的 qc 下):被壓縮到 ≤20ms 或在靜音內開始的詞具有不可靠的時間——在使用它們之前,請使用 timeline_view 檢查任何靠近這些詞的剪輯。

    • 多位說話者(通話、訪談):沒有說話者標籤。從內容推斷輪換(問題 vs 回答),然後使用 timeline_view 確認你計劃保留的每個短語(在視訊通話中,活躍說話者的圖塊會顯示誰在說話)。如果通話是每人一個音軌錄製的,請改用 --audio-track N 轉錄每個音軌。執行 pack_transcripts.py 以產生 takes_packed.md。取樣一兩個 timeline_view 以獲得視覺上的初步印象。
  2. 預先掃描問題。 對 takes_packed.md 進行一次掃描,記下口誤、明顯的失言或要避免的措辭。形成一個簡單清單,併入編輯者簡報。

  3. 對話。 以白話文描述你看到的內容。提出根據素材而定的問題。收集:內容類型、目標長度/長寬比、美學/品牌方向、節奏感覺、必須保留的時刻、必須剪掉的時刻、動畫與調色偏好、字幕需求。不要使用固定清單——每次的正確問題都不同。

  4. 提出策略。 4–8 句話:形狀、鏡頭選擇、剪輯方向、動畫計劃、調色方向、字幕風格、長度估計。等待確認。

  5. 執行。 透過編輯子代理簡報產生 edl.json。在模糊的時刻深入使用 timeline_view。在平行子代理中建立動畫。執行 validate_edl.py --fix 直到它以 0 退出。然後,如果需要字幕(字幕是從最終範圍建立的,因此任何範圍變更後都需重新執行),則執行 captions.py。

  6. 預覽。 validate_edl.py(不加 --fix)→ render.py --preview。

  7. 自我評估(在向使用者展示之前)。 在渲染輸出(而非來源)的每個剪輯邊界處(±1.5s 視窗)執行 timeline_view。檢查每個影像中的:

    • 剪輯處的視覺不連續性 / 閃爍 / 跳動
    • 邊界處的波形尖峰(從 30ms 淡化中漏掉的爆音)
    • 隱藏在疊加層後面的字幕(違反規則 1)
    • 疊加層錯位或顯示錯誤影格(違反規則 4)

    同時取樣:前 2 秒、後 2 秒以及 2–3 個中點——檢查調色一致性、字幕可讀性、整體連貫性。對輸出執行 ffprobe 以確認持續時間是否符合 EDL 預期。

    測量音訊,不要假設:ffmpeg -i out.mp4 -af ebur128=peak=true -f null - 以取得整合響度和真實峰值,以及每個區段的 RMS(對話、純音樂、結束卡)。結束卡比對話低 15 dB,或音效比語音大,都是錯誤。你無法收聽:請說明這一點,並回報數值。

    對於使用者將發布的任何內容(發布、宣傳、廣告),也請使用渲染後的檔案、EDL 以及使用者給出的任何參考影片,生成一個評論子代理。指示它進行批評,而非讚美:一個 verdict、按時間碼排列的排名問題及證據(影格、位準),以及應先做的 5 個修復。新鮮的眼光能看到作者不再看到的東西——被截斷的妙語、0.5 秒的迷因、在手機尺寸下無法閱讀的 28px 文字。

    如果有任何失敗:修復 → 重新渲染 → 重新評估。自我評估次數上限為 3 次——如果三次後仍有問題,請向使用者標記出來,而不是無限期循環。只有在自我評估通過後,才呈現預覽。

  8. 疊代 + 持久化。 自然語言回饋、重新計劃、重新渲染。絕不重新轉錄。在確認後進行最終渲染。追加到 project.md。

剪輯工藝(技術)

  • 音訊優先。 從詞邊界和靜音間隙中尋找剪輯候選點。
  • 保留高峰。 笑聲、妙語、強調節拍。將剪輯點延後到妙語之後,以包含反應——笑聲本身就是節拍。
  • 說話者交接時,話語之間留一些空白會更好。常見值:400–600ms。快節奏時用較少,電影感時用較多。這是品味判斷。
  • 笑聲和反應不會被標記(whisper 不會發射音訊事件)。在 timeline_view 波形中找到它們作為無語音但響亮的段落;將剪輯點延後到它們之後——笑聲本身就是節拍。
  • 靜音間隙是剪輯候選點。

相關技能