Communitygithub.com

daoge96/dsh-skills

以程式碼製作影片成品 — 一個純時間→影格渲染器,搭配經過驗證的渲染/編碼/封裝管線(動態圖形、資料動畫、解說影片、作品集、生成式循環、音訊反應式作品)。當交付目標是影片檔、循環動畫、要與音訊混合的影格序列,或需要驗證時長/fps/容器規格、迴圈接縫、「無任何靜止畫面」底線、連絡表審查、響度/真實峰值目標或渲染吞吐量時使用。在撰寫第一行繪圖程式碼之前載入。

dsh-skills 是什麼?

這個技能提供一個完善的以程式碼為核心的影片製作工作流程,將影片視為純函數 `render(t)` 和一個可測試的管線。它的設計目的是透過強制執行確定性(使用種子PRNG)、規範化為斷言(而非散文)以及優先考慮可觀察性與驗證來防止靜默錯誤。該技能適用於任何以程式碼為基礎的影片生成平台(如Claude Code、Cursor、Codex 或類似的 AI 編碼代理),並作為一個全面的指南來處理從初始規格到最終交付的整個影片製作流程,包括渲染、編碼、音訊處理和封裝。它包含兩個關鍵的零依賴腳本:`av_audit.mjs` 用於品質控制(容器驗證、運動分析、響度檢查和連絡表輸出),`mux_normalize.mjs` 用於音訊響度正規化和封裝。工作流程強調重要的反模式(例如透過白色複合畫面判斷顏色)和最佳實踐(例如幾天前就凍結時間合約、分解作者與驗證者的角色以及保持繪圖層的精簡與確定性),以確保生成的影片檔案達到專業品質。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/daoge96/dsh-skills/tree/HEAD/video-production

在你喜歡的 AI 中提問

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

說明文件

以程式碼製作影片

將影片視為一個純函數 render(t) 加上一個分階段的、可斷言的管線。此任務類別中幾乎所有的失敗模式都是無聲發生的單位/符號/頻道/指標錯誤——因此以下工作流程的設計目標是讓每個錯誤可被觀測。

0. 在繪製任何東西之前凍結合約

  1. 單一時間來源。 一切都在 render(t) 內部;影格↔時間對應 (t = frame/fps) 是唯一的公開 API。沒有 CSS 動畫、沒有計時器、沒有影格間狀態。結果:影格可平行化、可回復、可比較,且錯誤可定位到某個時間範圍。
  2. 確定性。 使用種子化 PRNG (hash(i)/mulberry32),絕不使用 Math.random;絕不使用 Date.now;將字型和紋理嵌入為 data URI,以便沒有網路/字型後備可以在執行中途改變像素。
  3. 將規格寫成斷言,而非散文。 時長、fps、解析度、編解碼器、像素格式、響度、真實峰值、安全區域/邊距、禁止技術、檔案路徑、CLI 標誌、退出碼、JSON 輸出形狀。如果簡報中有一個數字,它必須最終出現在檢查中。
  4. 事先決定接縫策略——一次性 / 迴圈 / 拼接片段。對於迴圈:每個振盪器是 sin(2π·k·t/D) 且整數 k;影片收斂回自己的第一個狀態(不是「看起來相似」);事件表和螢幕上的計數器/標籤在最終轉換中重置;驗證 render(0) 與 render(D) 的渲染結果。
  5. 每個影格的預算。 在建立內容之前測量 render(t)(1080p 畫布繪製為 2–30 毫秒;3 個子影格 × 5400 個影格會倍數增加)。記錄預算並遵守它。
  6. 凍結介面,然後對其進行雜湊。 畫布大小、頁面/API 表面、worker CLI、輸出路徑。所有 QC 都綁定到該修訂雜湊——針對過期雜湊進行的渲染 QC 是沒有價值的。
  7. 記錄有意的偏差。 每個與簡報不符的地方(「乾淨」線條上的網格抖動、小於規定最小值的微型字型、超出規定範圍的彈簧速率)都會以簡短清單記錄下來並附上原因,以便審查者可以判斷,而不是發現。

1. 第一天進行三項探測

探測斷言原因
捕獲完整性精確像素,alpha == 255,色彩範圍,存在第一/最後影格半透明累積、範圍/色彩空間錯誤會無聲地毀掉整個影片
成本render(t) 每個場景的毫秒分佈、記憶體現在架構變更很便宜,以後就很貴了
運動整個時長內的每個影格差異序列 + 最長的靜止運行時間立即顯示死時間範圍

源自真實失敗的規則:

  • 白色合成陷阱。 透過在白色上合成 alpha 的檢視器審查影格會隱藏半透明;編碼器是在黑色上合成。讓審查路徑與交付路徑完全相同的合成方式,並對兩者之間的像素進行差異比對。
  • 了解一個指標能看見什麼。 在 12 倍縮小後,細線的次像素運動會改變平均絕對差值約 0.03/255,而整個畫面的亮度變化則會改變約 1.5/255。如果驗收指標是縮小的平均值,最便宜的真正槓桿是全域值通道(例如,在節拍速率上加入 2 Hz ±3% 的亮度脈衝),而不是更大的擺動。
  • 在資產之前驗證指標。 當檢查失敗時,先傾印原始訊號(1 毫秒的包絡、像素行輪廓、影格數列)。一半的「資產有問題」最終是檢測器有問題。
  • 讓檢測器自描述。 建模並補償系統性偏差(濾波器群延遲、因果分析視窗延遲);偏愛最接近事件的候選者,而非最響亮的;永遠不要調整閾值直到它通過。
  • 精確與近似的主張。 "render(0) ≡ render(D), PSNR ∞" 是一個證明;"第一個與最後一個編碼影格相差 2/255(一個影格的運動)" 是一個觀察結果。切勿在報告中混淆兩者。

已打包:scripts/av_audit.mjs 實作了容器/運動/迴圈/響度/連絡表這一半(僅 ffmpeg,無 npm 依賴)。

2. 審查迴圈是一項功能,不是開銷

  • 將其網格化:數百張靜止圖片 → 十幾張連絡表,一次審查即可完成。
  • 內建導引:安全區域框、中心十字線、時間碼、事件 ID。審查者不必在腦中記住版面配置。
  • 按事件取樣,而非固定間隔:每個預期事件取一個影格,每個運動中間取一個影格。
  • 最仔細檢查接縫:場景轉場、迴圈包圍、片段邊界、第一/最後影格。
  • 隔離並放大可疑元素到空白畫布上 4–6 倍;大多數錯誤在全影格中是不可見的。
  • 成品是可拋棄的:一個命令即可重新產生;切勿手動修補審查影格。
  • 維護一個問題清單(雜亂/節拍不對/重疊/超出安全區域/無法閱讀/靜止),並在每次修正回合後重新審查。

3. 運動與迴圈工藝

  • 環境動作 ≠ 主要動作。 每個場景需要一個與主要動作不同頻率的連續頻道(漂移、波浪、空轉旋轉、數值脈衝),其零點與節拍對齊,以便動作仍能乾淨落地。這就是滿足「沒有任何東西是靜止的」的條件。
  • 一種緩動家族。 臨界阻尼彈簧 1-(1+x)e^-x(從不超調)用於移動;指數緩出/緩入用於擦除、按壓、退出。讓著陸與事件同時發生:開始 = 事件 − 持續時間,並歸一化,使得進度在事件發生時正好等於 1。
  • 兩個地方的運動模糊:在影格函數內部(2–4 個快門樣本,使用運行平均值平均——alpha = 1/(k+1)——最終完全不透明),在事件周圍更密集;加上編碼器端的時間混合。使用索引編碼的固定樣本(提供像素編碼影格編號的影格,並回讀哪些索引被平均了)證明濾波器視窗語義,切勿從文件推斷。
  • 透過構造實現連續性。 在場景之間攜帶一個幾何/狀態模型並對其進行轉換(變形、材質交換、硬邊擦除泛濫、掃描線),而不是剪切或溶解。
  • 保持長度的變形:透過角度/弧長參數化形狀,以便混合是增長而不是縮放。
  • 預設禁止清單(除非被要求,否則刪除):粒子、發光、鏡頭光暈、攝影機晃動、RGB 分離、交叉淡入淡出、通用漸層、彈性超調。

4. 渲染與編碼

  • 格式 vs 目標:首先測量吞吐量。無損 PNG 影格大小為數 MB,會給管道帶來壓力;高品質 JPEG 約快 1.5 倍。決定一次,然後保持不變。
  • 用管道,不要假脫機:將影格饋送到 ffmpeg 的 stdin(-f image2pipe -framerate <fps*sub> -vcodec png -i -)。使用 tmix 混合,選取組的最後一個影格,重新計時,用 -frames:v <n> 修剪。
  • 按成本平行化,而非影格數量。 測量每個場景的毫秒數,然後分割成時間大致相等的區塊;均勻的影格計數會讓最慢的 worker 決定總時間。
  • 片段必須可拼接安全:在每個端點重複 2 個邊界影格,相同的編碼器參數和時間基準,使用 ffprobe 驗證影格/時長,然後使用 -c copy 拼接。
  • 分階段進行管線,以便一個失敗只耗費一個階段:渲染 → 混合 → 編碼 → 音訊 → 封裝 → 測量;每個階段寫入一個檔案。
  • 在各階段之間保留無損影片主檔(到處使用 -c copy),並最後處理響度。
  • 在依賴之前先探測未知的工具鏈:濾波器/編碼器清單、瀏覽器可執行檔、版本;允許 $FFMPEG/$FFPROBE 覆蓋;優先使用固定的本地二進位檔案,而非 PATH 的猜測。與瀏覽器一起提供的精簡「媒體」ffmpeg 通常缺少 x264/tmix/loudnorm。
  • 透過檔案描述符捕獲子進程輸出,而非管道。 在受限的沙箱內,使用 stdio: 'pipe' 的 spawn/execSync 可能會因 EPERM 失敗,而同一個二進位檔案從 shell 執行卻正常。改為傳遞開啟的檔案處理器:spawnSync(cmd, a, { stdio: ['ignore', fdOut, fdErr] }),然後讀取檔案——對於純粹的存在性/版本探測,使用 stdio: 'ignore'。將 stdout 和 stderr 路由到不同的檔案,以便二進位影格數據不會與日誌文字交錯。
  • 從原始碼完成端到端重建,以便交付的檔案不是一個幸運的快取。

5. 音訊與封裝

  • 與畫面相同的時間基準和相同確定性(離線渲染、種子化、無即時依賴)。
  • 一個 cue 表({t, name})作為每個可聽/可視事件的唯一事實來源;SFX 存在自己的匯流排上,比音樂安靜。
  • 使用雙通道 loudnorm 正規化(print_format=json → measured_* → 第二通道加上 linear=true),然後使用獨立的第三方測量驗證;斷言整合響度在 ±0.5 LU 範圍內,且真實峰值 ≤ 目標。
  • 迴圈:將尾端淡出(~40 毫秒)到精確零點,第一個樣本無喀嚓聲;測量打擊樂對齊到網格並報告。
  • 封裝 -c:v copy -c:a aac -b:a <spec>,然後使用 ffprobe 檢查容器作為斷言,而非查看。
  • -b:a Nk 是 ffmpeg 原生 AAC 編碼器的目標,而非下限(在安靜素材上,對 320k 請求測量約 180–250 kbps;-aac_coder twoloop 有幫助)。讀回宣告的 bit_rate 並報告測量的平均值,而不是重複請求的數字,並在規格要求位元率時明確說明。

已打包:scripts/mux_normalize.mjs。

6. 保持繪圖層精簡且確定性

  • 快取所有隨時間不變的內容:預渲染背景、文字遮罩、圖案、Path2D。快取金鑰包含每個可能改變像素的參數。
  • 畫布池的大小必須來自來源畫布的尺寸,而非邏輯內容大小——否則 drawImage 會無聲地拉伸或裁剪(這導致了剪裁/損壞的文字)。
  • 在影格迴圈中避免使用 shadowBlur/filter;偏愛幾何圖形。
  • 記憶體:1080p 畫布約 8 MB;綁定池的大小。
  • 記住子影格數量會線性增加影格預算。

7. 協作

  • 分離作者與驗證者。 驗證者擁有 QC 腳本以及讓交付品失敗的權限,並獨立檢查作者未檢查的維度(alpha、與頁面的保真度、響度、迴圈閉合)。這能捕捉到作者視盲的錯誤類型。
  • 不重疊的寫入範圍 + 凍結的介面,以便平行工作不會衝突;對修訂進行雜湊,並在每次變更後重新執行 QC。
  • 大聲失敗:非零退出、每個主張一行 PASS/FAIL、機器讀取的內容使用 JSON、無靜默後備。

8. 反模式

  1. 透過白色合成的審查圖像判斷顏色。
  2. 編輯資產以滿足你從未表徵過的指標。
  3. 調整檢測器的閾值,而不是修復其模型。
  4. 重新執行完整渲染來回答一個 20 秒頁面端探測就能回答的問題。
  5. 在成本差異很大的場景之間使用均勻的影格計數分塊。
  6. 與交付路徑不同(縮放、色彩範圍、合成)的審查路徑。
  7. 「看起來不錯」而不是一個斷言;以退出碼 0 失敗。
  8. 使用會損壞非 ASCII 的工具進行文字/資產手術(編輯後驗證編碼)。
  9. 用手修正審查影格,而不是修正來源。
  10. 用交叉淡入淡出隱藏狀態不連續性。

9. 檢查清單

飛行前 — 規格 → 斷言;render(t) 簽章已凍結;接縫策略 + 迴圈代數;資產已嵌入;三個探測存在;每個影格預算已設定;FFMPEG/FFPROBE 已解析並探測過能力。

飛行中 — 每個場景後:成本探測、運動數列、事件取樣審查網格;問題清單已關閉;已編輯來源的語法/型別檢查加上非 ASCII 檢查;對修訂進行雜湊。

交付前 — 從原始碼重建;完整渲染(成本加權、邊界影格、已驗證拼接);響度雙通道 + 第三方驗證;獨立測量腳本 → PASS/FAIL;明確報告精確與近似的主張;刪除臨時腳本/截圖並記錄每個的一鍵再生。

完成的定義 — 容器元數據精確;接縫行為已證明;靜止運行限制已滿足;響度/真實峰值已滿足;螢幕上的文字與簡報逐字匹配;一個命令從原始碼重建;所有 QC 在凍結的雜湊上為綠色。

10. 已打包的腳本

兩者都是單一檔案、零依賴(僅 ffmpeg/ffprobe),從 $FFMPEG/$FFPROBE → PATH → 常見位置解析其工具,每個主張列印一行 PASS/FAIL,使用 --json 輸出 JSON,並在失敗時以非零退出。從此技能自身的路徑解析其目錄。

# QC 一個完成的檔案:容器與期望值、靜止運行限制、迴圈接縫、
# 響度/真實峰值、可選的供人工審查的連絡表
node av_audit.mjs film.mp4 --expect-duration 30 --expect-fps 60 --expect-size 1920x1080 \
     --static-limit 0.5 --sheets ./sheets        # exit 0 = 所有檢查通過

# 將 WAV 正規化到目標值並將其封裝到編碼後的影片上(影片串流複製),
# 然後使用第三方獨立測量通道驗證
node mux_normalize.mjs silent.mp4 score.wav film.mp4 --lufs -14 --tp -1 --abr 320k

av_audit.mjs 故意使用低解析度(160×90)MAD 數列:它看到的是整個畫面的值變化和區塊移動,而不是細線的次像素運動——將其與 §1 中的指標敏感度規則配對使用。對於迴圈,將 first_vs_last_psnr_db 視為關於一個影格運動的觀察結果,並透過比較渲染器本身的兩個渲染結果來分別證明精確性。

一句話總結 — 成功取決於三件事,而非繪圖技巧:時間函數是純淨且可驗證的、指標在被最佳化之前已被理解、以及審查與交付路徑是相同的路徑。

相關技能