TikTok / 抖音 短影片產生器
你(AI 代理)負責 創意 工作 — 腳本、場景拆解、搜尋關鍵字、風格選擇以及品質審查。scripts/ 目錄中的腳本負責 機械 工作 — 附帶時間戳的 TTS、素材搜尋與下載、字幕渲染、ffmpeg 合成、音量正規化。
所有流程僅需核心 ffmpeg(不需要 libass/drawtext)加上一個 Python 虛擬環境。不需要任何 API 金鑰即可運作;設定 PEXELS_API_KEY / PIXABAY_API_KEY 環境變數可以解鎖真實的庫存影片片段(效果更佳)。
工作流程
0. 一次性設定(如果已存在 .venv/ 和 assets/fonts/ 則可跳過)
bash scripts/setup.sh
1. 先驗證事實,再寫腳本 + 分鏡腳本
你的內部知識可能過時或有誤 — 切勿將未經驗證的陳述放入影片中。 在撰寫任何場景文字之前,請使用你的網路搜尋工具檢查每一個具體的陳述:數字、統計數據、記錄、價格、日期、排名,以及每一個「第一/最大/唯一/最快」的陳述 — 以及任何具有時效性的內容(新聞、產品、版本,「今年/最新」),無論你多麼確定。規則:
- 一條陳述只有在來源如此陳述時才能放入腳本 — 根據來源調整你的措辭,而不是反過來。
- 無法驗證?用你能驗證的陳述代替,或者刪除它。已發布影片中的錯誤數字比一個較弱的鉤子更糟糕。
- 記錄你在分鏡腳本
"sources": [...]中所依賴的 URL — 這些 URL 會在review/report.txt中回顯,以便用戶可以審核影片。 - 如果你真的沒有網路存取權限,請堅持使用長期確立的教材事實,避免具體數字,並告知用戶該影片未經驗證。
閱讀 references/writing-guide.md 了解腳本公式(鉤子類型、節奏、場景結構)。然後建立 projects/<slug>/storyboard.json:
{
"title": "深海里最诡异的5种生物",
"lang": "zh",
"aspect": "9:16",
"voice": "zh-CN-YunjianNeural",
"rate": "+10%",
"caption_style": "karaoke",
"bgm": {"mood": "mystery", "gain_db": -16},
"hook": {"text": "深海禁区", "seconds": 2.3},
"scenes": [
{
"text": "你知道吗?在阳光永远照不到的深海,藏着比科幻电影更诡异的生物。",
"keywords": ["deep sea NOAA ocean exploration", "submarine dark ocean"],
"providers": ["openverse", "wikimedia"],
"badge": null,
"effect": "kb_in"
},
{
"text": "第一名,鮟鱇鱼……",
"keywords": ["humpback anglerfish", "anglerfish museum"],
"badge": "第1名"
}
]
}
欄位參考:
| 欄位 | 值 | 備註 |
|---|---|---|
lang | zh | en | 設定字幕分組 + 預設語音 |
aspect | 9:16 (預設) | 16:9 | 1:1 | |
voice | 任何 edge-tts 語音 | zh: zh-CN-YunjianNeural(磁性男聲) zh-CN-XiaoxiaoNeural(女聲) zh-CN-YunxiNeural(陽光男聲); en: en-US-ChristopherNeural en-US-AriaNeural en-US-GuyNeural |
rate | 例如 +10% | 營銷號節奏:中文 +8%+15%,英文 +5%+10% |
caption_style | karaoke | pop | none | karaoke = 逐字高亮(推薦) |
bgm | {"mood": ...} | {"query": "style words"} | {"file": "path.mp3"} | {"mood":"none"} | 預設使用一個 mood:精選表格(歡快、有趣、勵志、輕鬆、科技、神秘、史詩、悲傷、恐怖)正是無數營銷號頻道運作的 MacLeod 經典曲目 — 經過驗證、安全、每個專案多樣化。只有在沒有 mood 符合內容風格時(或用戶指定了類型)才使用 query:它會搜尋真實的 CC 節拍音樂(ccMixter 風格標籤 + Openverse/Jamendo;排除 ND/NC),並且每個候選曲目都會經過節奏檢測器篩選 — 沒有確定的 75–175 BPM 節奏就不會選取。可對應到標籤的風格詞:trap/phonk, hip hop, lofi/chill, edm/dance, epic/cinematic, quirky。兩者可以同時設定 — 會先嘗試 query,mood 作為備用方案。file = 用戶自己的曲目 |
bgm.vibe | "spedup" | "slowed" | 不設定 | 抖音標誌性音效:spedup ≈ 1.25 倍速並提高音調(卡點/盤點影片的主流處理),slowed = 減速並加迴響(情感/氛圍向)。可應用於任何 BGM 來源(包括 file);處理後會重新分析節奏網格,確保卡點準確 |
beat_sync | true (預設) | false | 會分析 BGM 的節奏,當節奏網格可靠時,每個場景/鏡頭切換都會對齊到節奏網格(卡點);旁白永遠不會被截斷,只有呼吸暫停會彈性調整 |
hook | {"text","seconds"} | 在開頭顯示的大標題卡,≤ 8 個字/詞 |
sticky_title | {"text": ...} | 可選的持續性主題欄位於頂部;預設關閉 — 僅在用戶要求時才加入 |
sfx | true (預設) | false | 場景切換時的咻聲 |
場景 keywords | 英文、具體名詞查詢列表 | 每個條目 = 一個鏡頭(視覺);影片約每 3 秒切換一個新的視覺畫面,因此對於長度超過約 4 秒的場景,請給出 2–3 個查詢(如果你給的較少,會自動新增額外的鏡頭來循環你的查詢) |
場景 badge | 例如 "第1名" / "TOP 1" | 在場景開始時顯示的大標籤 — 用於列表類內容 |
場景 providers | 列表 | 無金鑰圖片:openverse wikimedia nasa;無金鑰真實影片:wikimedia_video(Commons 剪輯,伺服器轉碼)nasa_video(公共領域太空/科學)archive_video(Prelinger 公共領域歷史電影);有金鑰:pexels_video pexels_photo pixabay_video |
場景 effect | auto kb_in kb_out pan_left pan_right static | 第一個鏡頭的 Ken Burns 動畫;後續鏡頭會自動循環 |
場景 emphasis | 子字串列表 | 永久高亮的詞(pop 風格) |
場景 media | 檔案路徑 | 繞過搜尋,使用你自己的檔案(例如你自己下載的檔案) |
經驗法則(發布標準):總長 45–75 秒,6–9 個場景,每個場景一個想法,每個場景 2–3 個鏡頭。 場景文字 20–45 個中文字 / 14–30 個英文單詞。任何少於約 40 秒或全程只有單一鏡頭場景的影片都會感覺單薄 — 不要發布這樣的結果。
2. 執行管線
.venv/bin/python scripts/pipeline.py projects/<slug>
或者分段執行:tts.py → assets.py → bgm.py → compose.py → check.py。
3. 審查 — 這是決定品質的關鍵(強制)
免費圖片搜尋並不完美。請務必使用你的圖片檢視工具查看以下兩個檔案,並如同人類編輯一樣進行評判:
-
projects/<slug>/media/assets_sheet.jpg— 在素材階段之後。鏡頭會標示為01a 01b 02a …。對於每一個與旁白不符的鏡頭,重新取得它:.venv/bin/python scripts/assets.py projects/<slug> --scene 3 --shot 2 --keywords "better english nouns"(重新取得會自動將被拒絕的素材加入黑名單。重複此步驟直到所有場景都匹配。你也可以使用自己的工具自行下載圖像,並將場景的
media指向它。)管線還會對每個鏡頭的來源標題與其查詢進行文字審計,並印出
[!] OFF-TOPIC標記。如果你 目視確認 一個被標記的鏡頭實際上是正確的(例如一張沒有標題但非常完美的照片),請在media/manifest.json中將該鏡頭的"approved": true設定為 true 以清除標記 — 你的眼睛勝過文字審計。切勿盲目批准。 -
projects/<slug>/review/contact_sheet.jpg— 在合成+檢查之後。驗證:字幕可讀且同步、沒有錯誤/醜陋的畫面、鉤子可見。修正問題(編輯分鏡腳本 → 重新執行合成,速度很快)直到它看起來像一個營銷號編輯實際上會發布的影片。
review/report.txt 包含時長/音量檢查和一個即可貼上的 歸屬資訊區塊(CC-BY 來源 + 音樂致謝)— 務必與 final.mp4 一起提供給用戶。
素材搜尋技巧(最大的品質槓桿)
- 關鍵字必須是 英文,1–4 個詞,具體可見的名詞("humpback anglerfish"、"scuba diver silhouette"),永遠不要用抽象概念("mystery"、"success")。
wikimedia最適合動物/科學/歷史/地點;openverse(Flickr 等)適合生活風格/風景/氛圍;nasa適合太空;金鑰可以解鎖pexels_video/pixabay_video真實素材 — 有金鑰時優先使用這些。- 加入上下文詞來消除歧義:"NOAA"、"museum"、"aquarium"、"macro"。
- 如果一個場景持續失敗,改變視覺概念,而不僅僅是詞語(例如,對於「5% 被探索」,展示一個潛水員剪影,而不是「統計數據」)。
wikimedia_video搜尋支援否定詞 — Commons 的天氣/太空查詢會被衛星循環畫面淹沒,所以請寫例如"lightning storm -CIRA -satellite -JPSS"。非英文詞可以解鎖更多素材("Blitz Gewitter"、"tormenta rayos")。優先使用命名主體("Fagradalsfjall lava drone")而不是通用名詞,並且在圖表中務必仔細檢查影片縮圖:注意內嵌字幕、浮水印、教學和 CGI 宣傳片。
故障排除
edge-tts網路錯誤:它會重試 4 次;如果仍然失敗,重新執行tts.py。- BGM 下載失敗:重新執行
bgm.py(會重試 + 使用快取),或者使用--mood none,或者將 mp3 放入assets/bgm/並設定bgm.file。 - BGM 風格不符:優化查詢(
bgm.py <dir> --query "..."然後用--skip-tts --skip-assets重新合成)。對於 真正的當下熱門 音效,使用mood: none(或低增益)交付,並告訴用戶在上傳時從 TikTok/抖音的應用內授權音樂庫中新增熱門曲目 — 這既合法又受演算法青睞。剪輯時機仍然會很乾淨,因為場景節奏保持不變。 check.py會列印一行「切換是否落在節拍上」— 如果跳過了節奏同步(節奏網格置信度低,例如無節拍氛圍音樂),請選擇一首更穩定的曲目(--query "trap beat"等)並重新合成。- 某個提供者出錯/為空沒關係 — 其他提供者會覆蓋;請檢查每個場景的日誌。
- 在編輯分鏡腳本後重新合成成本很低(透過 pipeline.py 使用
--skip-tts --skip-assets,或直接執行 compose.py)。更改場景 文字 需要重新執行tts.py。 - 表情符號在 macOS(Apple Color Emoji)上可以渲染;在 Linux 上,除非安裝了 NotoColorEmoji,否則會被丟棄。永遠不要依賴表情符號來傳達意義。
交付
提供給用戶:final.mp4、來自 review/report.txt 的歸屬資訊區塊,以及(如果要求提供)review/cover.jpg 作為封面圖片。