Communitygithub.com

yahiafarid1/toon3d-story-shorts

製作一個約 45-65 秒、垂直式、卡通 3D 風格的動畫故事短片,使用 three.js 與 Remotion 在 Mac 上渲染。

toon3d-story-shorts 是什麼?

這個技能專為 AI 代理(如 Claude Code)設計,用於生成特定風格的短影音:1080x1920、30 fps、長度約 45-65 秒的完全原創動畫故事短片。其視覺風格是「3D 卡通風」,特點包括扁平 2D 白色頭部卡通角色、置入色彩鮮豔、帶有墨線輪廓的 3D 世界中、平滑無硬切的滑行鏡頭、逐字字幕、語速較快的旁白,以及搭配原創配樂和音效。 此技能主要用於當使用者要求製作「那種卡通 3D 風格」的短片,或是類似「假購物者/購物車影片」風格的歷史或科學故事短片。它也能協助發想病毒式主題、研究題材事實並編寫腳本,以及比對參考短片的風格與品質。 此技能建立在 mromidev/claude-animated-shorts (MIT 授權) 的基礎上,並修復了其審計中發現的所有差距。它提供了一個完整的工作流程,從發想主題開始,經過事實研究、腳本撰寫(遵循經過驗證的敘事公式,包括荒誕鉤子、懷疑者與轉折)、旁白生成與剪接、分鏡規劃(包含嚴格的鏡頭移動規則),到最終的 3D 場景搭建與渲染。所有步驟都包含審批關卡,以確保品質符合使用者偏好。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/yahiafarid1/toon3d-story-shorts/tree/HEAD/skill/toon3d-story-shorts

在你喜歡的 AI 中提問

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

說明文件

卡通 3D 動畫故事短片 (three.js + Remotion)

成果產出:一個 1080x1920、30 fps、45-65 秒的短片。以特定參考風格講述一個原創的真實故事:包含一個過去式的荒誕鉤子、嘲笑的反對者、「你看吧」的轉折點,然後是一句總結性的結尾。扁平卡通卡片立於一個帶有墨線輪廓的繪畫式 3D 世界中,搭配在冷色陰影襯托下的暖色定向光源、鏡頭模糊效果以及永不中斷的連續鏡頭。旁白語速較快(約每秒 3.7 字),搭配逐字字幕、原創配樂與合成音效,最終母帶處理至 -14 LUFS。

實作範例:「假購物者」 (1937 年,Sylvan Goldman 僱用演員來推他的新購物車),相關檔案位於 project/src/videos/fake-shoppers/ 和 project/stories/fake-shoppers/。

基本規則 (務必遵守)

  • 故事、角色、配音與音樂皆為原創。 參考影片僅用於視覺風格與公式,絕不可使用其腳本、角色或鏡頭畫面。切勿在任何影片、標題或描述中提到該參考頻道的名稱。參考影片是私人學習材料:絕不允許上傳或傳送它們。
  • 事實需經過研究並附上來源,並記錄在故事 SCRIPT.md 檔案的頂端。笑話應為誇飾或基於真實事實,切勿將虛構的歷史當作事實呈現。
  • 僅使用免費的本機工具。 使用 edge-tts 或使用者自己的聲音;不使用任何付費產生器。在任何使用 API 連接器產生費用前,務必先取得使用者同意。
  • 配音中無停頓 (將間隙剪至 0.07 秒,或句子結尾 0.2 秒)。字幕需開啟 (參照參考風格)。影片需在最後一個字結束後 ≤0.5 秒內結束,無片尾或 Call to Action。
  • 在選擇主題前,請先檢查 references/TOPICS_DONE.md。
  • 兩個審批關卡,然後「直接執行」 (沿用原始技能規則):
    1. 腳本: 展示腳本(附帶來源),並等待使用者確認腳本後,再進行配音與分鏡規劃。之後無需再次請示,直接進行到關卡 2。
    2. 審查板: 在進行完整渲染前,使用者會觀看一半尺寸的草稿,並在特定時刻或場景上釘上筆記,然後按下「看起來不錯」(步驟 8)。在此之前會重複修改;在審批通過前不得進行完整渲染。
  • 使用者的品味與已學習的檢查事項 (來自過去的審查板)。在撰寫腳本(步驟 2)、分鏡規劃(步驟 4)、場景設定(步驟 5)與角色設定(步驟 6)前,請閱讀兩個 PREFERENCES 檔案。在步驟 8 時,需要與 可讀性陷阱檢查 一起檢查這兩個 CHECKS 檔案:
    • 所有影片技能共享的檔案:~/video-editor/review-board/PREFERENCES.md、~/video-editor/review-board/CHECKS.md;
    • 此風格專用檔案:references/PREFERENCES.md、references/CHECKS.md。
  • 接手一個現有故事: 請先執行 node ~/video-editor/review-board/cli.mjs show stories/<name>/review。使用者在無連線階段時發送的筆記,需優先處理(步驟 8.5)。
  • 僅進行一次完整渲染。 在背景啟動渲染程序,告知使用者預估完成時間(1080p 約每秒 4 幀,2K 渲染 60 秒約需 10 分鐘),且不需輪詢:任務完成時會自動回報。使用 --scale 0.5 參數的預覽則可無限次重複進行。

此 Mac 環境 (設定與測試於 2026-11-07)

  • 工作目錄: ~/video-editor/toon3d-shorts/,由 setup.sh 建立。包含 src/engine (通用)、src/videos/<name>/ (每個影片一個資料夾)、stories/<name>/ (腳本、配音、提示、配樂)、audio/ (合成套件 + 混音器)、tools/measure.py、scripts/ 和 public/。此技能的 project/ 資料夾中有一份副本。任何位置可使用以下指令重新建立:bash ~/.claude/skills/toon3d-story-shorts/setup.sh <dir>,它會執行 npm install (固定版本) 和 pip install --user scipy。
  • Node 24 + Remotion 4.0.539: 透過 ANGLE/Metal 使用 GPU。在約 20 秒的打包後,每張靜態圖片約需 1.3 秒渲染;一個完整的 60 秒預覽在 --scale 0.5 參數下約需 45 秒。
  • Python 3.9: numpy, PIL, scipy。ffmpeg-full。whisper-cli 使用 ~/video-editor/models/ggml-large-v3-turbo-q5_0.bin 模型。edge-tts (python3 -m edge_tts)。
  • 參考研究 (由你自行建立,不包含在專案中): ~/video-editor/reference-study/,從你研究的參考短片中建立 (自行下載到 ~/Downloads/reference-shorts/;這些是學習材料,絕對不要分享)。作者研究了 19 部短片;references/ 中的數據即來自該研究:
    • STYLE_BIBLE.md 和 SCRIPTS_ANNOTATED.md
    • measure/ (逐幀統計、逐字稿、2 秒 / 60 幀連絡表、1 fps 幀、summary.json),用作 tools/measure.py ours ... --refs 的基準
    • frames/ 和 sheets/ (用於並排比較的 1 fps / 2 秒檢視)
  • 設定 TMPDIR/REMOTION_TMP 為 ~/video-editor/remotion-tmp (stills.mjs 會自動設定)。Remotion 的打包檔案會累積於此。只有當使用者同意時,才刪除舊的 remotion-webpack-bundle-* 資料夾。

工作流程

  1. 點子 → 主題 → 事實。 當使用者沒有特定主題,或要求發想時,進行一輪點子發想 (references/VIRAL_IDEAS.md 包含數據、來源、評分規則與事實規則):

    • 現在什麼題材會紅 (進行少量 YouTube 研究;若使用連接器會產生費用,請先詢問):

      • 參考頻道最受歡迎的短片:使用 youtube_channel_shorts,參數為 channel_id <REFERENCE_CHANNEL_ID> (你正在研究其短片的頻道) 和 sort_by popular。將任何新的標題加入 TOPICS_DONE.md。
      • 利基突破性題材:使用 faceless_outliers_videos,並根據贏家類型設定語意 query (例如「揭露奇怪歷史發明、詭計或法律背後隱藏原因的動畫短片,帶有轉折結局」),videoType 設為 shorts,languages 設為 ["english"],minOutlierScore 設為 3。忽略不符合利基的熱門題材 (如遊戲、小工具)。記錄標題模式,並將已被採用的故事加入 TOPICS_DONE.md。
    • 候選題材: 從來源列表中收集約 30 個真實故事,並使用 WebSearch/WebFetch。將每個故事映射到一個贏家類型:古老物品或習俗背後的隱藏原因、外國制度或漏洞、大腦心理學、金錢詭計或騙局、寓言或悖論。

    • 評分 每個題材,使用 10 項評分規則 (滿分 20 分)。針對前 10 名,使用 youtube_search (類型為 shorts) 檢查新鮮度:如果一個故事在過去 12 個月內已被製作過且觀看數超過 100 萬,則放棄該故事,或設法找到一個新的切入點。

    • 提出 5-8 個點子,內容包含:符合贏家模式的工作標題、一句話鉤子、核心物品、機制 + 類比、分數細項、為何可能病毒式傳播 (該類型的參考數據),以及 2-3 個來源。將所有點子儲存至 references/IDEAS_BANK.md。由使用者選擇一個。

    • 研究被選中的題材:

      • 每個數字、日期、名稱和主張,都需要 ≥2 個獨立且可靠的來源;
      • 傳說需標明為傳說;戲劇化的嘲諷需標明為如此;
      • 在 stories/<name>/SCRIPT.md 檔案的頂端建立一個事實區塊 (主張 → 連結 → 可信度)。

      對於大型主題,可以使用深度研究技能來完成此步驟。

    一個好的主題,是指一個令人驚訝的真實故事,包含一個核心物品、一個觀眾可以想像的隱藏機制,以及一個能夠解釋它的日常類比(例如碗、從桌上滑落的手機、電梯按鈕)。

  2. 腳本 (160-240 字,45-65 秒)。參考頻道的量化公式 (references/STYLE_BIBLE.md §2, SCRIPTS_ANNOTATED.md):

    • 鉤子 (在約 5 秒內完成,9-20 字): 以過去式敘述一個荒誕的行動作為事實(「他花錢僱人假裝在他的雜貨店裡購物。」)。替代方案:一個悖論式主張(「X 是非法的,但……」)或一個條件式承諾(「如果你曾經……」)。絕對不能是問句。
    • 場景設定: 1-2 句現在式句子,包含具體數字和年份。
    • 懷疑者: 有人嘲笑或模仿,並引用角色的嘲諷台詞。每個影片使用 1-2 次嘲諷。
    • 觀眾提問: 「等等,……?」/「但怎麼會?」(每個影片約一次)。
    • 升級: 時間跳躍和重複(「一週又過一週」、「到了七月……」),加上每 10-15 秒一個誇飾笑話(「X 到 Y 的程度」,一個縮小貶低的比較)。
    • 轉折: 「然後,某天晚上/早上……」。
    • 揭露: 「你看吧,」在影片約 65-87% 的時間點出現,用 1-3 句簡單的句子解釋真正的機制,理想上是透過日常類比。(「你看吧,」在鉤子之後立即使用也可以作為一個情境轉換。)
    • 結尾: 一句簡短的陳述句,重新定義一切(懷疑者被證明是錯的)。在此處直接結束。額外加分:將最後一句話設計成能與第一句產生循環,達到無縫銜接的效果。
    • 風格: 鉤子用過去式,然後轉為現在式;口語化的用詞並使用縮寫;每句約 14 個字;連接詞用「所以 / 但是 / 然後」,絕對不能用「然後」。第二人稱(「想像你……」)是有效的敘事模式。
    • 永遠不要旁白觀眾已經能看到的事物 (沿用原始技能規則)。配音應補充畫面無法呈現的資訊:原因、數字、笑點、利害關係。畫面則用於展示動作。
    • 標題: 圍繞核心物品建立一個好奇心缺口,4-8 個字,使用贏家模式(「那個[物品]做了[荒誕結果]」、「為什麼[群體]做了[奇怪的事]」、「一個[小東西]如何完成[大事]」、「[物品]的真正含義」、「那個[人物]的[悖論]」)。提供 3 個選項與腳本一起。
    • 鉤子測試: 大聲朗讀第一句話。它必須在約 3 秒內吸引注意力,並且聽起來不合理或不可能。如果需要情境鋪陳,請重新撰寫。
    • 提交關卡 1 審批: 腳本、3 個標題選項、以及包含來源的事實區塊。
  3. 配音 放入 stories/<name>/voice/:

    • 生成:執行 python3 -m edge_tts --voice en-US-AndrewNeural --rate=+14% --text "$(cat ../script.txt)" --write-media raw.mp3,或使用使用者自己的錄音。
    • 收緊剪接:執行 python3 scripts/tighten_voice.py raw.mp3 voice.wav --sentence-gap 0.12。這會將間隙剪至 0.07 秒,或句子結尾 0.12 秒(參考影片平均每部僅有約 1 個超過 0.25 秒的暫停),並輸出 48 kHz 單聲道音頻。
    • 單字時間戳記:在一個 16 kHz 的副本上執行 whisper-cli,使用 -l en -ml 1 -sow -oj 參數,然後轉換為 words.json ([{w, a, b}],單位秒)。使用腳本的拼寫,而不是 whisper 的猜測。同時複製一份到 words_authored.json:這是分鏡規劃所依據的時間線(story.ts 從這兩份檔案建立 RETIME;如果檔案內容相同,則表示無變更)。
    • 使用者自己的錄音: 將其單字與腳本進行比較,並測量其語速 (每秒字數、超過 0.25 秒的暫停次數)。對於已經很緊湊的朗讀,收緊剪接幫助不大;如果語速慢於以下目標,則製作一個保持音高但 --tempo 1.1 的版本,讓使用者聽過兩個版本後再選擇。
    • 在分鏡規劃後更換配音 (相同文字,新的錄音;於 2026-11-08 為「假購物者」所做):不要手動重新調整任何時間。
      • 保留舊的時間戳記作為 words_authored.json,並將新的時間戳記放入 words.json (腳本拼寫,字數相同)。不同的文字意味著需要新的分鏡規劃。
      • RETIME = makeRetime(authored, spoken, FPS) (engine/retime.ts) 將每一個輸出幀映射到作者時間線上,逐字跟隨新的配音並使用 ±2 字平滑處理(中位數起始時間誤差約 1 幀)。index.tsx 使用 total: RETIME.total, retime: RETIME;角色嘴形同步則繼續匯入 words_authored.json。
      • 在靜態圖片上檢查幾個關鍵字的幀,然後將新的草稿發布到審查板,並在 --changed 參數下列出每個場景。
      • 聲音會跟著調整,無需手動重新放置任何內容:
        1. 執行 node scripts/retime_cues.mjs <name>,保留 cues_authored.json 一份,然後寫入 cues.json (輸出時間的事件、dur 參數、背景音樂、嗖聲) 以及 timemap.json。
        2. 執行 python3 score.py music.wav <RETIME.total> timemap.json:重音會跟隨畫面,節拍網格則跟隨每個段落。如果沒有對應圖,配樂保持不變(逐樣本檢查)。
        3. 執行 python3 audio/mix.py stories/<name>/cues.json public/<name>/mix.wav,然後對混音檔執行 whisper 以確認每個字都能被聽到。
    • 目標:每秒 3.6-3.9 個字,鉤子需在 ≤6 秒內結束。TOTAL = ceil(最後一個字結束時間 × 30) + 6 幀。
    • 在分鏡規劃前收緊剪接,絕不能在之後進行。 每個鏡頭幀都基於收緊後的 words.json 建立,因此在之後重新收緊意味著重新調整整個影片的時間。(範例跳過了這一步,導致有 10 個超過 0.25 秒的暫停,而參考影片只有約 1 個。)
  4. 分鏡規劃 在 src/videos/<name>/story.ts 中 (參考範例):

    • SHOTS:{id, a, b, light, set},單位為幀。大約每 2.2 秒(約每 8 個字) 更換一個新視覺。動作應落在關鍵字上,在其開始前 0-3 幀。
    • TRANSITIONS:鏡頭如何進入:
      • dissolve (4-8 幀):用於地點或時間變更
      • iris (12-16 幀,cx/cy):透過舷窗、窺視孔、鏡頭或時鐘
      • dust (20-26 幀):當煙霧或雲團充滿畫面時
      • flash (4 幀):僅在鉤子之後使用 同一個場景中的鏡頭若無指定轉場,將自動通過鏈接式攝影機滑行來連接,滑行動作以場景邊界為中心 (makeCamAt;chain = 18 幀,或根據移動距離為每個進入的鏡頭設定一個記錄),使得場景轉換發生在移動過程中。絕不能使用硬切。 如果鏈接邊界的移動距離 > 約 1100 像素或轉彎角度 > 90°,則改用 dissolve 轉場。
    • CAMS:每個鏡頭的關鍵幀 {f, dur?, dissolve?, s: f => dolly(pos, look, pushK(f, f0, rate, punch?), {fov, roll})}。鏡頭規則 (references/studies/camera.md,基於 12 部短片,30 fps 分析):
      • 幀數預算:15-20% 靜止、約 45% 緩慢移動、約 33% 滑行(在 540 寬度下,每秒 3-30 像素)、≤3% 快速移動。
      • 約每 1.4 秒更換一次取景。大多數是小幅度重新取景:使用 withReframes(CAMS, ENDS) 包裝關鍵幀,讓每個長時間的靜止畫面每隔 42 幀就進行一次 14 幀長的左右平移,移動範圍為主體距離的 ±5%,同時保留該關鍵幀本身的推拉效果。標記有意的靜止畫面為 hold: true。每分鐘約有 4 次快速移動:峰值每秒 35-55 像素(上限 70),持續 20-34 幀。
      • 作者每 10 秒執行約 7 次移動,其中大部分是幅度小、速度慢的移動(峰值約每秒 10 像素,移動距離 80-150 像素)。使用 withNudges(CAMS, [[shot, baseKeyF, at, dur, ±0.05-0.07], ...]) 在長時間的靜止畫面內部進行小幅度的側向重新取景(保留該關鍵幀的推拉效果),然後 withReframes 會填補其餘部分。經此重新設定關鍵幀後,範例中的攝影機在每個類別上都測量到與參考相符的數值(靜止 19.5 / 緩慢移動 49.9 / 滑行 27.1 / 快速移動 3.5 %,每 10 秒 7.4 次移動;請見 studies/camera.md)。
      • 在靜態圖片上檢查每個微調的方向。 朝向……

… (其餘內容因篇幅限制而截斷)

相關技能