agentleFS
yojuhsuyojuhsu/video-cut/SKILL.md

video-cut

Skill1 starsChanged 2 months agoMITView on GitHub

從 macOS 照片圖庫自動找素材、用 GPS 與時間還原行程、剪成短片並上字幕配樂。當使用者說「幫我剪影片」「把某天的影片剪出來」「做一支旅遊短片」「這段影片幫我剪一下」「剪成 15 秒放脆」「剪個兩分鐘的」,或丟一個日期、地點、事件要成片時,務必使用此 Skill。涵蓋素材掃描與去重、畫中畫裁切、EDL 剪輯表、三種字幕、配樂、有人臉與無人臉雙版本。與 visual-gate 的分工:那支驗簡報與網頁,這支管影片,但同一條鐵則:看過畫面才算完成。

4 other projects use a version of this.

Adopted by

Most recently taken up by

  • Other versions4 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 4

    1. zenstory-ai/video-recap-skills★ 613same name
    2. JamalMohafil/claude-skills★ 27same name
    3. WhiteTowerAI/cut-as-code★ 16same name
    4. broomva/skills★ 4same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

The file

Files
SKILL.md

影片剪輯產線

從幾萬個檔案裡找出該剪哪些,剪成片,上字幕,配樂。

市面上的剪片工具都假設「你已經有一支片,告訴我怎麼剪」。這支 skill 補的是前面那段: 素材在哪、哪些能用、怎麼分群。


鐵則

  1. 渲染完要抽格看過。 程式沒報錯不等於畫面對。CLAUDE.md 第七原則在這裡沒有例外。
  2. 每輪只修 1 到 3 個最大落差。 看整支,講出最嚴重的那個,改完重新排序,不要照舊清單往下做。
  3. 素材數字從圖庫實際查。 「大概有幾百支」這種話會害你選錯版面和長度。
  4. 合成前逐段驗證。 渲染偶爾產出截斷的 mp4,moov atom not found,重跑該段就好。

五個步驟

#做什麼產出
1掃圖庫、去重、分群、抓地名assets.json、分群表
2抽格做檢視表,用眼睛選片*_v.jpg、*_p.jpg
3寫剪輯表edl.json
4渲染 → 抽格看 → 修 → 再看clips/*.mp4
5合成、配樂、輸出out/*.mp4

步驟 2 和 4 是這支 skill 的重點。選片和驗收都要靠眼睛,不能靠檔名和時長猜。


開工前的環境檢查

第一次在一台機器上跑,先確認:

for f in drawtext subtitles ass zscale overlay zoompan gblur; do
  printf "%-12s " $f; ffmpeg -hide_banner -filters 2>/dev/null | grep -qw "$f" && echo 有 || echo 沒有
done
ffmpeg -hide_banner -version | grep -c -- --enable   # 官方完整版 60+,精簡版 15 左右
python3 -c "import PIL; print('Pillow', PIL.__version__)"
command -v exiftool sips

如果沒有 drawtext 和 subtitles:不要重裝 ffmpeg 才動工。改用 Pillow 產字幕 PNG 再 overlay 疊上去,中文排版反而更好控制。scripts/render.py 就是這樣寫的。

如果沒有 zscale:做不了正規的 HDR→SDR tone mapping。iPhone 的 HLG 素材直接轉 8-bit 通常可以接受(實測藍天飽和、雲有層次、亮部不過曝),先做出來看,不要為這件事卡住。要更準的顏色再 brew reinstall ffmpeg。


步驟 1:掃素材

python3 scripts/scan_library.py --from 2026-06-10 --to 2026-06-22

它會複製 Photos.sqlite、查出區間內的資產、去重、分群、解出地名,寫成 assets.json 並印出分群表。

四個必踩的坑

.mov 的時間戳是 UTC,照片是當地時間。 QuickTime 的 CreateDate 存 UTC,HEIC 的 DateTimeOriginal 存拍攝地當地時間。 混在一起排序,影片會全部跑到早上,順序整個亂掉。用 --tz 指定拍攝地時區。

Live Photo 佔了影片檔的九成以上。 originals 裡的 .mov 有 96% 是 Live Photo 的 2–3 秒動態部分(檔名以 _3.mov 結尾)。 按副檔名抓片會剪出一團碎片。查 ZASSET.ZKIND=1 才抓得到錄影。

重複檔案。 同行的人 AirDrop 過來的素材可能被匯入兩次。用 (拍攝時間秒, 時長×100, 原始檔案大小) 三者相同判定重複。 實測一趟 13 天的行程裡有 80 個重複檔,沙丘那組 16 支影片有 5 組是同一支存兩份。

地名不要打外部 API。 照片圖庫本機的 ZADDITIONALASSETATTRIBUTES.ZREVERSELOCATIONDATA 是 NSKeyedArchiver plist, 裡面有 Apple 已經解好的地名。用 plistlib 讀,不用把使用者的 GPS 座標送出去。 鄉下地區可能只到「某某省」,這時候要問使用者實際地名。


步驟 2:選片

做檢視表,看過再選。

python3 scripts/sheets.py videos assets.json --out camp   # 影片,長片自動抽 3 格
python3 scripts/sheets.py photos assets.json --out camp   # 照片,可 --sample 3 抽樣

每格標了編號、時間、時長,編號跟 assets.json 的索引一致,直接拿來寫 EDL。

選片時要看的

  • 主角是誰。 常常不是風景。一隻被帶著走的玩偶、一台新車、一隻站在手臂上的鷹, 這些重複出現的東西才是片子的骨架。
  • 有沒有畫中畫。 iPhone 的雙擷取會在角落放一個自拍視窗, 橫拍在左上(約寬 27%、高 38%),直拍在右上(約寬 35%、高 25%)。 這會毀掉「無人臉版」,但不必整支放棄,用 crop 裁掉即可,見下面。
  • 長鏡頭要掃時間軸。 一支 96 秒的片,主體位置會變。 掃 8 個時間點,挑主體在裁切線右邊(或下方)的那一段,就能零損失地裁掉畫中畫。
  • 照片的 EXIF 方向。 sips 轉檔不會自動套用,縮圖會出現倒立和橫躺。 一定要走 PIL.ImageOps.exif_transpose。

步驟 3:寫 EDL

edl.json 是一個陣列,一個物件一格。

欄位意思
clip / photo素材編號,對應 assets.json 的索引
ss / dur從原片第幾秒開始、取幾秒(照片只要 dur)
zoom放大倍率,把直拍素材在橫式版面裡放大。1.0 不放大
crop[左, 上, 右, 下] 各裁掉的比例,用來去掉畫中畫
zdir照片的 Ken Burns 方向,1 推近、-1 拉遠。相鄰兩張用相反方向
place資訊卡,一到三行 ["06.13 05:47", "地點", "天氣"]
sub動作字幕,底部置中
poem詩詞。純 list 就是詩句;要署名用 {"lines":[...], "by":"唐・王績〈野望〉"}
audiotrue 保留這格的原聲。預設全部靜音,只有需要聽現場聲音的段落才開

浮水印走環境變數,不必寫進每一格:

MARK="yoursite.com ; edited by Claude" VW=1920 VH=1080 ... python3 render.py

小字半透明,貼在畫面最下緣,跟動作字幕分層不會撞。 | title | 片頭標題 ["主標", "副標"],第三個元素給 "top" 可貼上方,避免壓到畫面正中的主體 | | end | 片尾卡 ["主標", "副標", "說明"],會加半透明黑底 |

長度怎麼抓

用途長度每格格數
Threads/IG 循環15 秒1.8–2.2 秒8
一般短片60–90 秒2.5–3.5 秒25–30
完整記錄100–130 秒2.4–6 秒35–40

15 秒循環是另一種東西,不是把長片剪短。 它沒有時間鋪陳,要靠一個重複的動作 當引擎(同一個主角、背景一直換),首尾用同一個視覺元素收口,接回去就看不出接縫。 字幕最多一行放在最後,loop 時它會變成節拍點。


步驟 4:渲染與驗收

VW=1920 VH=1080 CDIR=clips EDL=edl.json CONCAT=concat.txt CARDS=cards python3 scripts/render.py
VW=1920 VH=1080 CDIR=clips EDL=edl.json CONCAT=concat.txt CARDS=cards python3 scripts/render.py 3 12 21   # 只重跑指定段

全部的環境變數:

變數預設意思
VW / VH1080 / 1920輸出尺寸。16:9 用 VW=1920 VH=1080
CDIRclips片段輸出目錄
EDLedl.json剪輯表檔名
CONCATconcat.txtconcat 清單檔名
CARDScards照片卡片目錄
VIDEOSvideos.json影片清單。全照片的片子可以沒有這個檔
WORKDIR當前目錄工作目錄,一般不用設
MARK無浮水印文字,設了就每格都疊在畫面最下緣

所有輸出都相對於「執行時的當前目錄」,不是腳本裝在哪裡。 所以可以把 skill 裝在 ~/.claude/skills/,cd 到專案目錄再呼叫它。 片段落在 ./clips/,字幕圖在 ./ovl/。

出 9:16 直式版:VW=1080 VH=1920。同一份 EDL,兩個版面都出得來。

合成前逐段驗證:

cd clips && for f in *.mp4; do
  ffprobe -v error -show_entries format=duration -of csv=p=0 "$f" >/dev/null 2>&1 || echo "壞: $f"
done

抽格看畫面(這步不能跳):

python3 scripts/sheets.py check out.mp4 edl.json --out chk

每格抽中點,拼成檢視表。看完講出最嚴重的 1–3 個問題,改完重新排序。

版面怎麼選

橫拍和直拍混在一起的時候,實際渲染兩版比一比,不要用猜的。判準是哪一邊的主體損失小:

  • 主角特寫多半是直拍 → 9:16 滿版
  • 風景和地標多半是橫拍 → 16:9 滿版
  • 少數派用模糊背景填滿,或用 zoom 放大裁切

zoom 放太大會切掉主體。直拍在 16:9 裡放到 1.2–1.3 通常安全,超過 1.5 要看過再決定。


步驟 5:配樂與輸出

消原聲配音樂(原聲多半是風聲和雜訊,削弱效果):

MUS="/Applications/iMovie.app/Contents/Resources/iMovie Theme Music/SIMPLE2.m4a"
ffmpeg -y -f concat -safe 0 -i concat.txt -c copy -an muted.mp4
D=$(ffprobe -v error -show_entries format=duration -of csv=p=0 muted.mp4)
FO=$(python3 -c "print(round(float('$D')-4,2))")
ffmpeg -y -i muted.mp4 -stream_loop -1 -i "$MUS" \
  -filter_complex "[1:a]atrim=0:$D,asetpts=PTS-STARTPTS,afade=t=in:d=2.5,afade=t=out:st=$FO:d=4,loudnorm=I=-19:TP=-2:LRA=11[a]" \
  -map 0:v -map "[a]" -c:v libx264 -preset slow -crf 23 -pix_fmt yuv420p \
  -c:a aac -b:a 160k -ar 48000 -shortest -movflags +faststart out.mp4

只留幾段原聲(現場演奏、有人說話)

在那幾格的 EDL 加 "audio": true,其他格自動靜音。合成時讓音樂在那幾段降下去:

DUCK="between(t,74.5,79.0)+between(t,81.5,85.5)"   # 從 EDL 累加算出來的區間
ffmpeg -y -i raw.mp4 -stream_loop -1 -i "$MUS" -filter_complex "\
[1:a]atrim=0:$D,asetpts=PTS-STARTPTS,volume=0.50,\
volume=enable='$DUCK':volume=0.22,\
afade=t=in:d=2.5,afade=t=out:st=$FO:d=4[m];\
[0:a]volume=2.0[o];\
[m][o]amix=inputs=2:duration=first:normalize=0,alimiter=limit=0.92[a]" \
  -map "[a]" -c:a aac -b:a 160k -t $D audio.m4a

實測原聲段會比周圍音樂大 4–5 dB,聽得很清楚。

分三步做,不要一次到底。 118 秒的 1080p 影片用 preset medium 壓縮要五分鐘, 一次做完常常撞到逾時而產出截斷的檔案:

  1. -an 只壓影片
  2. 單獨混音訊成 .m4a
  3. -c copy 合併

這樣任何一步失敗都能單獨重跑,不用整支重來。

保留全部原聲(現場演奏、有人說話的片子)時,各段音量落差常有 20 dB, 用 loudnorm 會把安靜的段落硬抬成噪音。改用 dynaudnorm 做動態正規化:

-af "dynaudnorm=f=250:g=7:p=0.75:m=8,afade=t=in:d=1.0,afade=t=out:st=$FO:d=2.5,alimiter=limit=0.92"

實測七段 -23 到 -43 dB 的原聲,這樣拉平到 -16 到 -17 dB。

保留原聲就不能切太碎。 現場音樂被剁成 3 秒一段會很難聽。 這種片子改成只切 2 到 3 段、每段 8 到 9 秒,接點靠淡入淡出軟化。

音樂哪裡來

/Applications/iMovie.app/Contents/Resources/iMovie Theme Music/ 有七首, Apple 授權可用於自己的作品。/Library/Audio/Apple Loops/ 有上千個 loop,同樣授權。 不要從網路抓來路不明的音樂。

沒辦法聽的時候用數據選:

ffmpeg -hide_banner -i "$f" -af "highpass=f=4000,volumedetect" -f null - 2>&1 | grep mean_volume
ffmpeg -y -i "$f" -filter_complex "showwavespic=s=900x120" -frames:v 1 wave.png

高頻能量越低音色越柔和,波形起伏越平穩越不搶戲。有規律脈衝的是舞曲,背景音樂不要選。


三種字幕,不要只有一種

只有日期地點會很乾。混著用:

類型放哪寫什麼
資訊卡 place段落開頭,左下時間、地點、天氣
動作字幕 sub有動作的鏡頭,底部置中白話、有畫面感、帶一點情緒
詩詞 poem遠景空鏡,底部偏上見 references/poems.md

動作字幕怎麼寫:講畫面上正在發生的事,不要抒情。 「牧民騎馬而來,一整排」「駱駝站起來的瞬間,會先往前傾」「奶茶是鹹的」。

詩詞位置:試過畫面上方三分之一,會壓在地平線和主體上。放底部, 前景多半是草地沙地,最不擋事。逗號改用全形空格,中文詩排起來才像詩。

天氣:陰晴可以從畫面確認,敢寫。溫度查得到的多半是月份氣候平均,不是當天實測, 不要把月平均寫成當天氣溫。


片頭與片尾

片頭可以是一格,也可以是「一個 cut 加二到三張關鍵照片」的快切: 第一格帶標題(2 秒),後面三張各 1.2 秒無字,像預告。選能代表全片的三張。

挑主鏡頭時選最有衝擊力的那格,標題疊上去。 挑之前先渲染出來看:遠景的主體在 16:9 裡會變得很小, 直拍縮進橫式版面只剩中間一條,這種當片頭撐不住。

片尾用一個「離開」感的鏡頭(人物遠去、鏡頭上搖),疊半透明黑底加三行卡: 地點、日期、這支片有什麼。


有人臉與無人臉雙版本

需要對外發布時常要兩版。無人臉版不是把有人的鏡頭刪掉就好:

  1. 畫中畫:crop 裁掉,見步驟 2
  2. 主畫面裡的人:整段排除,裁切救不回來
  3. 照片也要逐張看:縮圖上看起來是駱駝,放大才發現上面坐著人

做完無人臉版,把用到的每一張照片並排重看一次再交件。實測這步抓到兩張漏網的。

「不要人臉」通常指的是使用者自己和同行的人,當地人的臉多半是可以留的(那是內容本身)。 先問清楚,這決定可用素材是差一倍還是差一半。


純照片也能撐完一支敘事片

條件是素材本身有時間軸。實測一支 44 秒的馬拉松紀錄,一支影片都沒用到 (賽事當天的錄影全是 0 到 7 秒的碎片),十六格全是照片,但完全成立,因為:

  • 里程牌是天然的節奏器。6 MILE、21 MILE、35 KM、38 KM 一格一個, 推進感自己會出來,不需要旁白解釋「跑了很久」。
  • 表情變化是天然的弧線。天亮前的笑臉到 38 公里的自拍,中間什麼都不用說。
  • 時間戳當字幕。04:21 15:15 17:51 直接寫進句子開頭, 十一個小時的跨度用兩個數字就講完了。

判斷素材夠不夠:找得出五個以上有時間標記的節點(里程牌、路標、時鐘、 日出日落、餐點)就可以,找不出來就別硬做,那會變成配樂幻燈片。

節奏要快慢交替,不是整體加快

想加快不要全片壓短,字幕格壓短會讓長句讀不完。改成兩種格分開處理:

類型每格說明
字幕格2.2–5.0 秒依字數給時間。中文約每秒 5 字,30 字就要 5 秒
快切格1.2–1.4 秒無字幕的路人、空景、連拍。眼睛掃過就好

快切段插在敘事段之間,四到八格一組。慢—快—慢—快—慢的起伏比等速好看, 而且快切段最好落在故事本身也緊湊的地方。

橫拍素材混進 9:16 的快切段要加 zoom(2.0 以上), 不然一半滿版一半細條,眼睛會一直被打斷。

結尾的順序:先回答,再留餘韻

如果片中出現過問句或懸念,結尾要先回答它,再收在餘韻上,順序不能反。

實測那支馬拉松:倒數第四格是「結束了,真的嗎?」,緊接著給終點拱門和獎牌 (回答「真的」),最後才收在曬傷加上「隔年春天都還有印記」。

如果收在獎牌,那就跟所有完賽影片一樣。收在曬傷,時間被拉到半年後, 才是這支片獨有的東西。但沒有前面的回答,餘韻會變成沒交代。

封面圖另外出一張

社群平台自己抓的縮圖多半是第一格,而第一格常常是鋪陳用的暗畫面,滑過去不會停。 從 cards/ 挑一張最有識別度的,用 Pillow 疊上大標題另存 JPG:

  • 主標放比賽或地點名,副標放日期
  • 最有力的數字放最大(成績、天數、距離),用金色
  • 底部保留浮水印

標題保持資訊型就好。如果字幕已經是自嘲或抒情的口氣,標題再跟著走會變成同一個調, 外層資訊、內層情緒,兩層才有對比。

從長片切系列短片

一支長片剪好之後,同一批素材可以再切成幾支 15–20 秒的主題短片。 一支一個主題(早晨、某個活動、某個地點),各自獨立成立,適合連續發。

每支給一張資訊卡開場,全程掛浮水印,不要片頭片尾卡(太短,撐不起來)。

配樂取同一首的不同段落,四支就 0s / 15s / 30s / 45s,淡入 1.5 秒。 這樣連著看不會覺得是同一段音樂重播。

這裡有個會咬人的坑:-ss 45 之後音樂只剩 15 秒,配上 -shortest 會把 20 秒的影片砍成 15 秒,而且不報錯。實測中招過一次。 音樂起點靠後時一定要加 -stream_loop -1,並用 -t $D 明確指定長度。 輸出後逐支比對「EDL 總長」和「實際長度」,差超過 0.5 秒就是被截了。

交付

輸出兩個檔:母帶(CRF 19)和上傳版(CRF 23 + faststart)。 超過 30 MB 的檔案傳不進對話,要告訴使用者只能在桌面版看,並附上 open 指令。

留下 edl.json 和 README.md,說明改哪個檔、怎麼重跑、這台機器有什麼坑。 下次要剪同一趟的另一支,複製整個資料夾改日期就好。

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.