stickman-explainer 是做什麼的?
將一個簡短的腳本轉換為完成的 1080×1920 mp4。你撰寫一個故事板 JSON;scripts/render.py 會繪製每一幀(搖晃的墨線條,8 fps 線條沸騰,淡入/擦除/彈出顯示效果)並使用 ffmpeg 編碼。
assets/example_storyboard.json 僅作為語法範例(3 個場景);請勿將其佈局或角色配件複製為範本。
視覺風格預設值
- 使用 9:16 畫布(1080×1920,30 fps)。每個場景保持在一個概念,通常 2.5–4 秒,字幕保持在平台安全區域內。
- 使用溫暖的紙色(
#f3ebdd)、深色墨線(#2b2723)和語義磚紅色強調色(#b8372d)。太陽金色(#d89d48)僅可選用於太陽主題。保持其他部分扁平:無漸層、陰影或 3D 效果。 - 使用清晰的臉部和充足的留白繪製簡單的黑墨色人物。除非故事或用戶要求,否則請勿添加頭盔、皇冠、斗篷、紅色衣物或其他配件。請勿從歷史名稱推斷服裝。
- 保持場景可讀性:最多 2 個角色和 5 個小圖示。讓主體突出;避免字幕和道具重疊。不超過 2 行字幕。
- 使複雜道具易於辨識。繪製一個具有清晰交叉環、緊密中心和可見繩端的繩結。為劍繪製清晰的握柄、護手和尖銳劍身。切割後,在兩條繩端之間留下可見間隙。
- 當旁白時間點可用時,使紅色字幕強調色在旁白過程中跟隨當前口語的單詞。為每個以空白分隔的字幕單詞使用一個
karaoke區間;非活躍的單詞保持正常文字顏色。 - 偏好不對稱佈局並刻意留下留白。地面線條、太陽、標題卡、對話框和其他主題為可選;僅在它們支援場景時選擇使用。
工作流程
- 腳本 → 場景。 將故事拆分為一句一個場景(字幕 ≤ 6 個單詞,每個 2.5–4 秒)。模式:標題卡 → 鉤子/衝突 → 具體揭示。每個場景只增加一個新資訊。當提供旁白時,場景邊界應與口語句子對齊。
- 為每個句子選擇一個視覺。 每個場景一個隱喻:角色 + 道具、對話框、或一排圖示(X = "不具有")。保持 ≤ 2 個角色和 ≤ 5 個圖示。
- 撰寫故事板(結構如下)。對於逐字旁白時間點,為每個以空白分隔的字幕單詞添加一個
karaoke區間,使紅色強調色跟隨正在發音的單詞。只有在單詞時間點不可用時才使用**word**進行靜態高亮;請勿將靜態標記與karaoke結合使用。 - 先檢查靜態圖片(快速,約 2 秒/場景):
python scripts/render.py story.json --stills out/stills→ 開啟每個scene_NN.png,修正重疊/放置問題,重複執行。 - 草稿影片:
python scripts/render.py story.json out/draft.mp4 --draft(無超採樣,12 fps)。 - 最終版本:
python scripts/render.py story.json out/final.mp4 [--audio voiceover.mp3]。 場景時長應與旁白句子長度匹配;使用ffprobe測量音訊並相應設定duration。單詞區間是從其場景開始的秒數,應來自旁白對齊或仔細聆聽。確保每個紅色單詞與其口語音訊同時出現,既不提前也不延後。
錯誤訊息與驗證
render.py 在繪製故事板前會進行驗證:未知的 type/pose/face/kind/font、缺少必填欄位、同一場景中重複的 id、duration <= 0、單點 lines 路徑、奇數(非偶數)解析度以及不存在的 carry id 將以明確訊息拒絕,而非回溯追蹤。對於永遠不會顯示的元素(場景結束後的 at)會發出警告。如果音訊檔案比影片短,結尾將填充靜音;如果較長,則會被截斷;影片長度絕不會改變。
故事板結構
{"meta": {"width":1080,"height":1920,"fps":30,"boil_fps":8,"transition":0.18,
"palette":{"accent":"#b8372d"}, "audio":null, "font_dirs":[]},
"scenes":[{"duration":3.4, "caption":"是偉大的 **亞歷山大**。",
"caption_at":0.5, "caption_y":null, "elements":[ ... ]}]}
對於跟隨語音的單詞強調,請提供一個 karaoke 陣列,其中包含 caption 中每個以空白分隔的單詞一個 { "start": seconds, "end": seconds } 物件。時間是相對於場景的;紅色強調色在每個區間切換。當存在 karaoke 時,字幕不得包含 **...** 標記。
{"duration":2.8, "caption":"他一手刀劈開了繩結。", "caption_at":0.35,
"karaoke":[{"start":0.35,"end":0.76},{"start":0.76,"end":1.02},
{"start":1.02,"end":1.53},{"start":1.53,"end":2.15}],
"elements":[ ... ]}
每個元素:type,可選 id(用於延續)、at(秒,出現時間)、dur(顯示秒數)、anim = fade | wipe | rise | pop、until/out_dur(淡出秒數)。
位置 x、x2、y、ground ≤ 2 時被視為寬度/高度的比例,否則為像素。尺寸始終為像素。
| 類型 | 關鍵欄位 |
|---|---|
ground | y(必填);x、x2 可選,若未提供則約為畫布的 ~2%–98% — 搖擺的基線 |
sun | x、y、r、rays |
text | text(**accent** 標記)、x、y、size、font = sans/sans_bold/sans_light/serif、tracking、caps、color、max_w、max_lines(預設 3)、rules(用於標題卡的雙線;寬度和間距根據文字自動調整) |
figure | x、ground、h、head_r、pose = stand/arms_open/point/wave/think/shrug/sit、dir(±1)、face = neutral/smile/sad/surprised/angry、可選 accessory = helmet/crown/hat/glasses、可選 cape、look |
prop | kind = barrel/bowl/bucket/house/book/box/triangle/coins/tree、x、y(左上角)、w、h、cross(強調色 X)、flip |
thought | x、y、w、h、tail_to [px,py](頭部位置)、inner:氣泡本地像素座標中的元素列表 |
lines | paths(點的列表的列表,本地像素)、closed、smooth、color、width — 用於任何自訂形狀的逃生口 |
場景間的連續性(延續)
要將一個場景的元素帶到後續場景,請為該元素賦予 id,並在下一個場景中使用 carry 引用它。攜帶的元素以相同的線條震動(相同的種子)開始,使其看起來像是「同一幅畫」,即使場景變換;新的場景過渡預設為剪切(無交叉淡入淡出)。
"carry": [
"ground",
{"id": "sun", "set": {"r": 122}},
{"id": "alex", "set": {"x": 120, "face": "smile"}, "tween": {"at": 0.1, "dur": 0.9}},
{"id": "diog", "until": 0.1, "out_dur": 0.5}
]
各行依序:"ground" 按原樣攜帶 · sun 攜帶但修改欄位(修改在場景開始時立即生效) · alex 同時修改欄位並在持續時間內調整位置(tween) · diog 被攜帶但在場景內淡出。
"carry": "all"攜帶所有內容("carry_except": ["id", ...]排除特定項目)。字幕永遠不會被攜帶。- 未攜帶的元素在場景開始時立即消失;使用
until/out_dur實現平滑淡出。使用until淡出的元素不能攜帶到下一個場景。 tween僅動畫位置(x 和 y/ground);尺寸(r、h、w)和外觀(face、pose)的變化在場景開始時立即應用。- 攜帶的元素在新元素的下方繪製。要攜帶的元素在場景間的
id必須是唯一的。 - 具有相同
id的元素在每個場景中使用相同的種子;不要為場景特定的新元素賦予id。
透過擴展 render.py 中的 PROPS / hands 來新增道具/姿勢;保持相同的墨線風格(使用 stroke(),永遠不要使用普通線條)。
佈局:每次影片重新決定
無固定座標/範本。由於每個影片的主題不同,請從場景內容推導佈局:
- 首先選擇該句子的單一視覺概念(比較、列表、夢想、旅程、數字…),然後建立與之匹配的佈局。同一個影片中,場景間的佈局可以改變。
- 為重要元素留出空間:主體應該是最大/最突出的;次要元素保持較小。刻意留出空白(負空間)。
- 大小、位置和數量根據內容變化(1 個還是 2 個角色;圖示條、單個大型物體還是地圖/時間線)。必要時使用
lines繪製自訂形狀。 - 請勿為歷史人物自動添加服裝/頭飾。人物預設繪製為無配件模式;頭盔、皇冠、帽子或斗篷僅在敘述或用戶明確要求時添加。請勿將強調色擴散到角色的服裝上作為裝飾。
- 在繩結和切割場景中,以可讀的方式建構物體:用幾個明顯重疊的環圈繪製繩子,在中心顯示緊密的繩結,並區分繩端。劍應可辨識出握柄、護手和尖銳劍身。切割後,將兩條切斷的繩端清晰間隔並明顯可見;劍和繩結不應被字幕遮擋。使用
lines繪製自訂的繩子/劍形狀。 - 地面線條、太陽、標題卡等主題是可選的;如果不適合主題則不要使用(例如室內、夜晚、抽象概念)。
- 將字幕放在可讀且遠離平台 UI 的位置;如果衝突,調整
caption_y。在靜態圖片中目視檢查衝突和溢出,不要依賴數字。 - 繪製座標以像素(或 0–2 範圍的比例)給出,基於 1080×1920 畫布;為每個場景從頭規劃數值。
注意事項
- 在編碼前務必檢視靜態圖片;重疊元素和裁剪的太陽光線是常見缺陷。使用
--draft進行草稿,使用完整渲染處理細節:不變的幀不會重繪,10 秒的影片全品質約需 20 秒。 - 字幕會換行至 86% 寬度(最多 3 行),但如果一個單詞無法容納或超過 3 行,則會縮小。將超過 2 行的句子拆分為兩個場景。預設字幕位置僅為備用;必要時在場景中提供
caption_y。 - 字型:安裝 Poppins 和 Playfair Display(或 Lora),或提供
--font-dir。如果找不到 TrueType 字型,渲染器將列印警告,且土耳其語字元(İ ş ğ â)可能缺失;在靜態圖片中檢查。會掃描 Linux、macOS 和 Windows 字型資料夾。 - 保持強調色的語義性(主體、關鍵字、否定)。不要添加更多顏色。
- 當存在
karaoke時,紅色字幕強調色使用提供的區間逐字跟隨旁白。不要在螢幕上留下固定的紅色關鍵字;以字幕文字顏色渲染非活躍的單詞。