Communitygithub.com

Prateekiiitg56/ffmpeg-pipeline

針對腳本影片編輯的生產級 ffmpeg 管線:偵測、旋轉與 VFR 修正、HDR/HLG/Dolby Vision 轉 SDR 色調映射、Apple Log、分段擷取、無損串接、xfade 轉場、覆疊時間、PNG/Alpha 覆疊、字幕燒錄、速度調整、畫質提升,以及 Instagram、TikTok、YouTube 和母版的輸出預設。

ffmpeg-pipeline 是什麼?

這是一個專業的 ffmpeg 管線技能,專為需要精確、可重複影片編輯的開發者與 AI 代理設計。它提供從原始素材到最終輸出的完整流程,解決了常見陷阱,如 iPhone 的旋轉標記、可變幀率(VFR)以及 HDR 色調映射(HLG/PQ)。此技能支援多個平台,包含 Instagram、TikTok、YouTube 以及 ProRes 母版輸出,並提供清晰的腳本(如 probe.py、export.py、frames.py)來簡化工作流程。其核心架構圍繞一個「build 腳本」模式,其中每個片段會先獨立處理(修剪、速度、調色、幀率轉換),再透過 concat demuxer 進行無損串接,或用 xfade 濾鏡添加轉場。覆疊、字幕與音訊則在最終階段加入,確保效能與靈活性。對於 AI 代理而言,這個技能意味著他們可以整合到自動化編輯流程中,利用 EDL(編輯決策列表)與腳本化的 build.py 來處理大量素材,同時維持輸出品質與一致性。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Prateekiiitg56/video-editing-skills/tree/HEAD/skills/ffmpeg-pipeline

在你喜歡的 AI 中提問

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

說明文件

ffmpeg 管線

輔助腳本位於此檔案旁的 scripts/ 目錄中。使用 python <skill_dir>/scripts/<name>.py 執行它們。

  • probe.py IN... — 每個檔案一行摘要(大小、fps、旋轉、HDR、時長、音訊)。
  • export.py IN OUT --preset instagram|tiktok|shorts|youtube|master|preview — 使用正確設定進行最終編碼。
  • frames.py IN OUTDIR --times 0.5,3,7.2 或 --every 1 — 抓取參考幀。

1. 先偵測與標準化

手機素材常見陷阱:

  • 旋轉:iPhone 會儲存橫向像素加上一個旋轉標記。ffmpeg 會在解碼時自動旋轉(-noautorotate 可停用)。OpenCV 的 VideoCapture 可能不會自動旋轉 — 請檢查 frame.shape 並自行旋轉。
  • VFR:手機錄製可變幀率。在提取時轉換為 CFR:-vf fps=30(或使用 -r 30 輸出),這樣幀數計算才會精確。
  • HDR:color_transfer=arib-std-b67(HLG)或 smpte2084(PQ)。未經處理,在 SDR 下看起來會發白/灰。進行色調映射:
# HDR(HLG 或 PQ)-> SDR Rec.709,CPU zscale 路徑
-vf "zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p"

hable = 擬電影風格;mobius 可保留更多飽和度。若缺少 zscale,請使用 libplacebo(-vf libplacebo=tonemapping=bt.2390:colorspace=bt709:color_primaries=bt709:color_trc=bt709)。

  • Apple Log / 相機 Log:先套用製造商的 Log → Rec.709 LUT(lut3d=AppleLog_to_Rec709.cube),再進行調色。
  • 10-bit 來源:當需要重度調色時,在中繼階段保留 10-bit(ProRes 用 -pix_fmt yuv422p10le 或 x265 用 yuv420p10le);只在最終匯出給社群平台時才轉為 8-bit yuv420p。

2. Build 腳本的架構

sources/(從不修改)
edit/
  build.py          # 從來源 + 資料檔案重新產生所有內容
  edl.json          # [{src, in, out, speed, grade, transition}]
  segments/         # 每個 EDL 項目一個已調色、標準化的檔案(近乎無損)
  overlays/         # PNG / PNG 序列 / ProRes 4444 / WebM Alpha
  preview.mp4, final.mp4

規則:

  1. 分段提取,在一次處理中完成所有每個片段的操作(修剪、速度、縮放/裁切、調色、fps)→ 以 -crf 10(x264)或 ProRes 422 HQ 產出中繼檔案。
  2. 串接:當不需要轉場時,使用 concat demuxer 搭配 -c copy 串接片段(所有片段必須共享相同的編解碼器、解析度、fps、pix_fmt、時間基數)。
  3. 覆疊與文字:在串接後的影片上進行一次最終處理,然後根據交付規格進行一次編碼。
  4. 音訊則獨立建置(音樂 + 音效 + 對話 → 一個 WAV),然後在最終處理時混流。

精確修剪

# 當重新編碼時(ffmpeg >= 2.1),-ss 放在 -i 之前速度快且幀精確
ffmpeg -ss 12.40 -i IN.mov -t 2.333 -vf "fps=30,scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920" \
  -c:v libx264 -crf 10 -preset medium -pix_fmt yuv420p -an seg_003.mp4

對於必須幀精確的修剪,絕對不要使用 -c copy(它會對齊到關鍵幀)。

從 16:9 填滿成 9:16

  • 裁切(封面):scale=-2:1920,crop=1080:1920:(iw-1080)*X:0,其中 X 為 0..1 來選擇主體位置(若主體移動可進行追蹤)。
  • 模糊背景(包含):split[a][b];[a]scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,boxblur=40:2[bg];[b]scale=1080:-2[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2

串接

# list.txt:  file 'segments/seg_001.mp4'(每行一個)
ffmpeg -f concat -safe 0 -i list.txt -c copy joined.mp4

使用 xfade 的轉場

ffmpeg -i a.mp4 -i b.mp4 -filter_complex \
 "[0:v][1:v]xfade=transition=fade:duration=0.5:offset=4.5,format=yuv420p[v]; \
  [0:a][1:a]acrossfade=d=0.5[a]" -map "[v]" -map "[a]" out.mp4

offset = 第一個片段時長 − 轉場時長。類型:fade, fadeblack, fadewhite, wipeleft, slideup, smoothleft, circleopen, radial, zoomin, hblur, pixelize, dissolve…對於多個片段,需累加計算偏移量(每個 xfade 會縮短總長度,時長等於其 duration)。

覆疊

# 靜態 PNG(全畫面、透明)套用到整部影片 — 不需要 -loop
[0:v][1:v]overlay=0:0:format=auto
# 限時
overlay=0:0:enable='between(t,2.0,5.5)'
# 從輸出時間 T 開始的動畫覆疊片段
[1:v]setpts=PTS-STARTPTS+T/TB[ov];[0:v][ov]overlay=0:0:eof_action=pass

Alpha 覆疊:PNG 序列(-framerate 30 -i ov/%04d.png)、ProRes 4444(-c:v prores_ks -profile:v 4444 -pix_fmt yuva444p10le)或 VP9 WebM(-c:v libvpx-vp9 -pix_fmt yuva420p)。 對於長影片,不要使用 -loop 1 來處理 4K RGBA PNG;它會消耗大量記憶體。覆疊濾鏡會自動重複單一圖像輸入。

從 Python(PIL/OpenCV 合成)將原始幀管道傳送到 ffmpeg:

p = subprocess.Popen(["ffmpeg","-y","-f","rawvideo","-pix_fmt","rgb24","-s",f"{W}x{H}","-r","30","-i","-",
                      "-c:v","libx264","-crf","12","-pix_fmt","yuv420p","out.mp4"], stdin=subprocess.PIPE)
p.stdin.write(frame.tobytes())   # numpy uint8 HxWx3,每幀

同樣地,以 -f rawvideo -pix_fmt rgb24 - 讀取來源幀,這樣可以避免 OpenCV 的旋轉和編解碼器問題。

速度

  • 恆定:setpts=PTS/2(2x)+ atempo=2.0(atempo 範圍 0.5-100;需要更多時可鏈式使用)。
  • 從 30 fps 平滑慢動作:minterpolate=fps=60:mi_mode=mci:mc_mode=aobmc:vsbmc=1,然後 setpts=2*PTS。注意邊緣/手部可能出現變形。
  • 可變速度曲線:根據時間映射逐幀渲染(請參考 beat-sync),切勿堆疊多個 setpts 表達式。

字幕(最後階段)

-vf "subtitles=captions.ass:fontsdir=fonts"     # ASS 提供完整的樣式控制

3. 輸出預設

目標影片音訊備註
Instagram Reels / TikTok / Shorts1080x1920(或 2160x3840)H.264 High, 30 fps, CRF 16-18, -maxrate 25M -bufsize 50M, yuv420pAAC 48 kHz 256-320k加上 -movflags +faststart;平台會重新編碼,所以請餵入高品質檔案
YouTube 16:93840x2160 或 1920x1080, H.264 CRF 16 或 HEVC CRF 18, 來源 fpsAAC 48 kHz 320k即使內容是 1080p,也上傳 4K 以獲得更好的 VP9/AV1 編碼
母版ProRes 422 HQ 或 x264 CRF 10 / x265 CRF 14 -tag:v hvc1PCM 24-bit 48 kHz歸檔用
預覽720p, CRF 28, -preset veryfastAAC 128k快速疊代用

務必為社群平台加上 -pix_fmt yuv420p(10-bit 或 4:2:2 可能在上傳後失敗或顯示異常),並加上 -color_primaries bt709 -color_trc bt709 -colorspace bt709 以正確標記 SDR。

4. 驗證

ffprobe -v error -show_entries stream=codec_name,width,height,r_frame_rate,pix_fmt -show_entries format=duration -of compact out.mp4
ffmpeg -i out.mp4 -af ebur128=peak=true -f null - 2>&1 | tail -12
ffmpeg -i out.mp4 -vf "select='gt(scene,0.3)',showinfo" -f null - 2>&1 | grep pts_time   # 查看實際剪輯點在哪裡

Individual skills in this repo

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

相關技能