Communitygithub.com

影片製作

每當使用者想要建立、編輯或轉換影片檔案(.mp4、.mov、.webm、.gif)時使用此技能——包括從圖片製作幻燈片、添加文字或字幕的剪輯、修剪、合併、加入音樂或旁白、調整大小以適應社交媒體,或將動畫渲染成影片。

影片製作 是什麼?

這項「影片製作」技能專為以程式化方式從原始素材(影片、圖片、音訊檔案)建構與編輯影片而設計,使用 ffmpeg 作為核心引擎,並輔以 Python 的 Pillow 與 MoviePy 函式庫進行更進階的操作。對於由程式碼生成的動態圖形(如動態文字、解說影片、動畫圖表),請改用 `motion-graphics` 技能。此技能支援所有主流 AI 代理平台(如 Claude Code、Cursor、Codex),並提供可套用於真實專案的命令。最佳實務強調「先規劃後建立」:在執行任何命令前,先確定長寬比、影格率、長度與音訊需求,並撰寫簡短的鏡位清單。然後透過腳本檢查工具鏈,確保 ffmpeg、ffprobe 與 Python 套件已安裝。標準編碼設定(`-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -movflags +faststart`)確保輸出檔案能在手機、QuickTime 與瀏覽器上播放。為加快渲染速度,建議將每個場景編碼為獨立檔案,再以 `-c copy` 無損合併,避免每次修改時重新計算整個影片。另外提供十餘種常見需求的食譜,包括圖片幻燈片(含淡入淡出與 Ken Burns 效果)、文字覆疊、修剪、合併、加入背景音樂、字幕、調整為直向、改變速度、高品質 GIF 轉換,以及用 Pillow 逐格繪製動畫。交付前必須用 ffprobe 與聯絡表單(contact sheets)驗證持續時間、解析度、編碼與可讀性,並檢查常見陷阱(如 iPhone 無法播放、尺寸非偶數、影音不同步等)。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/SahilRakhaiya05/Father-Using-This-Skills/tree/HEAD/plugins/video-making

在你喜歡的 AI 中提問

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

說明文件

影片製作技能

對於由程式碼製作的動態圖形——動態文字、解說影片、發表會影片、動畫圖表、可選擇視覺風格的片尾文字——請使用 motion-graphics 技能。此技能適用於原始影片、照片、音訊以及 ffmpeg 編輯。

使用 ffmpeg(核心引擎)和 Python(Pillow 處理影格/圖形,MoviePy 進行高階編輯)以程式方式建構影片。始終先規劃、再建構、最後驗證。


1. 規劃先行

在撰寫任何指令前,先確定這些事項:

決策預設值備註
長寬比16:9(1920x1080)Reels/Shorts/TikTok 用 9:16(1080x1920),動態牆用 1:1(1080x1080)
影格率30 fps電影感用 24,螢幕錄影/遊戲畫面用 60
長度依要求Reels/Shorts 通常 ≤ 60–90 秒
格式MP4(H.264 + AAC)幾乎到處可播;僅在指定時才用 WebM;僅用於短循環才用 GIF
音訊可選音樂、旁白或無聲

撰寫簡短的鏡位清單:每個場景 → 持續時間、視覺、文字、轉場、音訊。


2. 檢查工具鏈

which ffmpeg ffprobe || (apt-get update && apt-get install -y ffmpeg)
python3 -c "import PIL, moviepy" 2>/dev/null || pip install pillow moviepy --break-system-packages
fc-list | head   # 查看可用的字型

3. 標準編碼設定

除非使用者指定其他方式,否則每次最終渲染都使用這些設定:

-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -movflags +faststart \
-c:a aac -b:a 192k
  • -pix_fmt yuv420p — 在手機、QuickTime 和瀏覽器上播放的必要條件。
  • -movflags +faststart — 讓影片在完全下載前就可以開始播放。
  • -crf 18 = 接近無損(檔案較大),-crf 28 = 檔案較小,畫質較低。
  • -preset veryfast 可保持快速渲染;只有在要求最佳畫質時才使用 slow。
  • 寬度和高度必須是偶數才能在 H.264 中使用。

3b. 快速渲染——使用者正在等待

完整渲染是最慢的步驟,因此每個請求請規劃一次完整渲染:

  1. 編碼前先預覽。 以最終尺寸抽取或繪製幾個影格——最忙碌的時刻、第一個和最後一個影格——並檢查構圖、文字大小和顏色。對於照片影片:scripts/slideshow.py OUT.mp4 photos… --preview 可在幾秒鐘內產生聯絡表單。
  2. 場景,而非單一巨大圖表。 將每個場景編碼成獨立檔案,使用相同的尺寸、fps 和編碼器設定,然後用 concat demuxer 和 -c copy 將它們合併,最後再用 -c:v copy 加入聲音。之後修正一個場景只需要重新編碼該場景。
  3. 轉場效果存在於場景檔案內部(在其邊緣淡入/淡出)。對兩個已完成的檔案進行交叉淡出會強制進行第二次完整編碼。
  4. 節省靜態畫面的成本。 使用 loop 濾鏡將圖片解碼一次並重複使用,而不是使用 -loop 1(後者會為每一影格再次解碼圖片): ffmpeg -framerate 30 -i still.png -vf "format=yuv420p,loop=-1:1,trim=duration=4,setpts=PTS-STARTPTS" -c:v libx264 -preset veryfast -crf 20 -pix_fmt yuv420p still.mp4
  5. 絕不使用真實名稱保留未完成的檔案。 寫入到 name.part.mp4,只有當 ffmpeg 以狀態碼 0 退出時才重新命名——即使渲染中斷,該檔案仍可播放,只是內容會被截斷。
  6. 除非使用者特別要求,否則以輸出尺寸和 30 fps 繪製影格。當逐影格截取網頁畫面時,儲存為 JPEG(品質約 90),而不是 PNG——寫入和讀取速度快得多。

在 10 張照片 → 1080p 上測量:舊的單一 -loop 1 + xfade 圖表耗時 13.2 秒;slideshow.py --crossfade 耗時 6.4 秒,場景檔案路徑(含音樂)耗時 8.9 秒。

修改完成的影片:

變更做法
修改某個場景的內容重新渲染該場景檔案,再用 -c copy 重新合併
更換音樂 / 修剪結尾-c:v copy(新音樂:-map 0:v -map 1:a)
燒錄字幕、製作較小副本對完成的檔案重新編碼一次
每格都不同的變更無法避免地需要一次完整渲染

4. 食譜

4.0 用單一指令製作圖片幻燈片

python3 scripts/slideshow.py out.mp4 photos/*.jpg --seconds 3 --fade 0.5 --music song.mp3      # 快速,透過黑畫面淡入淡出
python3 scripts/slideshow.py out.mp4 photos/*.jpg --crossfade                                 # 真實交叉淡出
python3 scripts/slideshow.py out.mp4 photos/*.jpg --zoom --size 1080x1920                      # Ken Burns 效果,直向

4.1 手動從圖片製作幻燈片(含淡入淡出轉場)

# 每張圖片顯示 3 秒,0.5 秒交叉淡出,縮放/補邊至 1080p
# 每張靜態圖片只解碼一次,並用 loop 濾鏡重複使用(比 -loop 1 快 2 倍)
F="scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,setsar=1,format=yuv420p,loop=-1:1,trim=duration=3,setpts=PTS-STARTPTS,fps=30"
ffmpeg -framerate 30 -i img1.jpg -framerate 30 -i img2.jpg -framerate 30 -i img3.jpg \
-filter_complex "\
[0]$F[a];[1]$F[b];[2]$F[c];\
[a][b]xfade=transition=fade:duration=0.5:offset=2.5[ab];\
[ab][c]xfade=transition=fade:duration=0.5:offset=5[out]" \
-map "[out]" -c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -movflags +faststart slideshow.mp4

片段 n 的偏移量 = (前面所有持續時間的總和)−(n × 淡出持續時間)。

4.2 Ken Burns 效果(在靜態圖片上緩慢縮放)

# d = 輸出影格數(30 fps 下 150 格 = 5 秒);不需要 -loop,zoompan 會產生影格
ffmpeg -i photo.jpg -vf "scale=3840:-2,zoompan=z='min(zoom+0.0008,1.2)':d=150:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':s=1920x1080:fps=30" \
-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p zoom.mp4

先將圖片放大到 3840 可以避免 zoompan 在小圖片上顯示的抖動現象。

4.3 文字覆疊 / 標題卡片

ffmpeg -i input.mp4 -vf "drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf:\
text='我的標題':fontsize=72:fontcolor=white:box=1:[email protected]:boxborderw=20:\
x=(w-text_w)/2:y=h-150:enable='between(t,0,4)'" \
-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -c:a copy titled.mp4

對於包含撇號、表情符號或非拉丁文字(如印地語等)的文字,請使用支援該文字系統的字型,透過 Pillow 將文字渲染成 PNG,然後再疊加它:

ffmpeg -i input.mp4 -i title.png -filter_complex "overlay=(W-w)/2:H-h-100:enable='between(t,0,4)'" ...

4.4 從無到有建立純色標題卡片

ffmpeg -f lavfi -i color=c=0x111827:s=1920x1080:d=3:r=30 \
-vf "drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf:text='第一章':fontsize=96:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2" \
-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p card.mp4

4.5 修剪片段

# 精確修剪(重新編碼):從 00:00:05 開始,持續 10 秒
ffmpeg -ss 00:00:05 -i input.mp4 -t 10 -c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -c:a aac trimmed.mp4
# 快速修剪(不重新編碼,在最近的關鍵影格處切斷)
ffmpeg -ss 00:00:05 -i input.mp4 -t 10 -c copy trimmed_fast.mp4

4.6 合併片段

相同的編碼/解析度/fps → concat demuxer(不重新編碼):

printf "file 'a.mp4'\nfile 'b.mp4'\nfile 'c.mp4'\n" > list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy joined.mp4

不同來源 → 先標準化(scale, fps, audio rate)或使用 concat 濾鏡:

ffmpeg -i a.mp4 -i b.mp4 -filter_complex \
"[0:v]scale=1920:1080,setsar=1,fps=30[v0];[1:v]scale=1920:1080,setsar=1,fps=30[v1];\
[v0][0:a][v1][1:a]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" -c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -c:a aac joined.mp4

(如果某個片段沒有音軌,請加入靜音音軌:-f lavfi -i anullsrc=r=48000:cl=stereo 並使用 -shortest。)

4.7 加入背景音樂

# 影片下的音樂,結尾淡出,在影片結束時停止
# st = 影片長度減去淡出長度(此處為 30 秒影片,3 秒淡出)——使用 ffprobe 取得長度
ffmpeg -i video.mp4 -i music.mp3 -filter_complex \
"[1:a]volume=0.3,afade=t=out:st=27:d=3[m]" \
-map 0:v -map "[m]" -c:v copy -c:a aac -shortest with_music.mp4

# 將音樂混合到現有說話聲之下
ffmpeg -i video.mp4 -i music.mp3 -filter_complex \
"[1:a]volume=0.15[m];[0:a][m]amix=inputs=2:duration=first[a]" \
-map 0:v -map "[a]" -c:v copy -c:a aac mixed.mp4

4.8 字幕 / 隱藏式字幕

撰寫一個 .srt 檔案:

1
00:00:00,000 --> 00:00:03,000
歡迎觀看這部影片。

2
00:00:03,000 --> 00:00:06,500
以下是我們將要涵蓋的內容。

燒錄字幕:

ffmpeg -i input.mp4 -vf "subtitles=subs.srt:force_style='FontSize=24,PrimaryColour=&HFFFFFF,OutlineColour=&H000000,BorderStyle=1,Outline=2'" \
-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -c:a copy captioned.mp4

4.9 為社交媒體調整大小(直向 9:16)

# 使用模糊背景填充,而非黑色邊條
ffmpeg -i landscape.mp4 -filter_complex \
"[0]scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,boxblur=20[bg];\
[0]scale=1080:-2[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2" \
-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -c:a copy vertical.mp4

4.10 加速 / 減速

# 2 倍速(影片 + 音訊)
ffmpeg -i in.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" fast.mp4

4.11 影片轉 GIF(高品質)

ffmpeg -i in.mp4 -vf "fps=15,scale=640:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 out.gif

4.12 從程式碼渲染影格(動畫、圖表、動態圖形)

當 ffmpeg 濾鏡不夠用時,用 Python 繪製每個影格並將其拼接起來:

from PIL import Image, ImageDraw, ImageFont
import os, subprocess

W, H, FPS, SECONDS = 1920, 1080, 30, 4
os.makedirs("frames", exist_ok=True)
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 96)

for i in range(FPS * SECONDS):
    t = i / (FPS * SECONDS)
    img = Image.new("RGB", (W, H), (17, 24, 39))
    d = ImageDraw.Draw(img)
    x = int(-600 + t * (W + 600))          # 文字橫向滑過
    d.text((x, H // 2 - 48), "你好!", font=font, fill=(255, 255, 255))
    img.save(f"frames/{i:05d}.png")

subprocess.run(["ffmpeg", "-y", "-framerate", str(FPS), "-i", "frames/%05d.png",
                "-c:v", "libx264", "-preset", "veryfast", "-crf", "23",
                "-pix_fmt", "yuv420p", "-movflags", "+faststart", "animation.mp4"], check=True)

使用緩動函數(例如 t*t*(3-2*t))以獲得更平滑的運動效果。

4.13 MoviePy(快速高階編輯)

from moviepy import VideoFileClip, TextClip, CompositeVideoClip, concatenate_videoclips, AudioFileClip

clip1 = VideoFileClip("a.mp4").subclipped(0, 5)
clip2 = VideoFileClip("b.mp4").subclipped(2, 8)
video = concatenate_videoclips([clip1, clip2], method="compose")
music = AudioFileClip("music.mp3")
video = video.with_audio(music.subclipped(0, min(video.duration, music.duration)))   # 音樂可能較短
video.write_videofile("out.mp4", fps=30, codec="libx264", audio_codec="aac", preset="veryfast")

(顯示的是 MoviePy 2.x 的 API;1.x 使用 subclip/set_audio。請用 pip show moviepy 檢查版本。)


5. 交付前驗證

絕不在檢查前交付影片:

# 持續時間、解析度、編碼、fps
ffprobe -v error -show_entries format=duration:stream=codec_name,width,height,r_frame_rate -of default=nw=1 out.mp4

# 在關鍵時刻抽取靜態影格並檢查
ffmpeg -ss 1 -i out.mp4 -frames:v 1 check_1s.png
ffmpeg -i out.mp4 -vf "fps=1/3,scale=480:-1,tile=4x2" -frames:v 1 contact_sheet.png

檢查清單:

  • 持續時間與規劃相符
  • 解析度和長寬比正確;沒有不想要的黑色邊條或拉伸
  • 文字清晰可讀,在安全邊距內(距離邊緣約 5%;對於 9:16,避開底部約 15% 的區域,因為那裡會放置應用程式 UI)
  • 轉場正確落在預期位置
  • 音訊存在(如果預期有)、沒有爆音、結尾乾淨
  • 可在手機上播放:H.264、yuv420p、偶數尺寸

6. 常見陷阱

問題解決方案
影片無法在 iPhone/QuickTime 上播放加入 -pix_fmt yuv420p
"width not divisible by 2"使用 scale=1280:-2 而非 -1
使用 -c copy 修剪後開頭出現黑影格重新編碼,或在 -i 之前放置 -ss 然後重新編碼
合併後影音不同步在合併前標準化 fps 和音訊取樣率(-ar 48000)
xfade 錯誤 "inputs differ"所有輸入必須有相同的尺寸、fps、setsar=1 和像素格式
drawtext 在 ' 或 : 處中斷對其進行跳脫處理,或使用 textfile= / Pillow 渲染的 PNG 疊加
非英文文字顯示為方塊使用支援該文字系統的字型(例如 Noto Sans Devanagari)
檔案大小過大提高 CRF(26–28),降低 fps 或解析度
渲染速度太慢使用 -preset veryfast 或 ultrafast;在初稿階段降低解析度

7. 工作流程摘要

  1. 規劃 — 長寬比、fps、長度、鏡位清單、音訊。
  2. 收集素材 — 圖片、片段、音樂、字型;用 ffprobe 檢查它們。
  3. 快速初稿 — 使用低解析度 / ultrafast 預設來檢查時間點。
  4. 建構最終版本 — 使用標準編碼設定(第 3 節)。
  5. 驗證 — 使用 ffprobe + 聯絡表單 + 檢查清單(第 5 節)。
  6. 交付 — 傳送最終檔案,並附上一行摘要(持續時間、解析度、內容說明)。

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相關技能