A field guide to the markdown + image "bible" behind an AI cartoon seriesคู่มือเตรียมไฟล์ Markdown และภาพ "คัมภีร์เรื่อง" สำหรับซีรีส์การ์ตูน AI为 AI 卡通剧集搭建 Markdown 与图像「设定集」的实战指南
Set up the metadata before the story begins — then let the pipeline runเตรียมเมตาดาทาก่อนเรื่องจะเริ่ม แล้วปล่อยให้ไปป์ไลน์ทำงาน在故事开始前备好元数据,然后让流水线自己跑
The whole idea in one sentenceแก่นทั้งหมดในประโยคเดียว一句话讲清整个思路
If you write down who, where, and how it looks — as plain markdown files and reference images — before the story begins, then turning a script into animated episodes becomes a mechanical loop a machine can run for you.
Why front-load the metadata?ทำไมต้องเตรียมข้อมูลไว้ก่อน为什么要提前准备好元数据?
The hard part of an AI cartoon is not generating one pretty frame. It's making frame #800 show the same girl, in the same village, drawn in the same style, as frame #1.
AI 卡通的难点不在于生成一张漂亮的画面,而在于让第 800 帧里出现的,仍是第 1 帧那个同样的女孩、同样的村庄、同样的画风。
Image and video models have no memory between calls. Every shot is a fresh roll of the dice. The only thing that carries consistency from shot to shot is the text and reference images you feed in. So a series lives or dies on its reference layer — and the smartest time to build that layer is up front, once, before you animate anything.
Think of it like a real studio's show bible: character turnarounds, location maps, a style guide, a script. The animators never re-invent the character — they look it up. We do the same, except our "animators" are animagine-xl for stills and Wan 2.2 for motion, running locally on the Spark.
可以把它想成真实工作室的「设定集」:角色转面图、场景地图、风格指南、剧本。动画师从不重新发明角色——他们查阅设定。我们也一样,只不过我们的「动画师」是负责静帧的 animagine-xl 和负责动态的 Wan 2.2,都在本地的 Spark 上运行。
The payoffผลตอบแทน回报
Once the bible is complete, every later step — pick a scene, assemble its prompt, render the still, animate it, add voice, stitch — reads from files. That's exactly the shape a script can automate. Preparation is the creative work; production is plumbing.
The visual DNA: lineart weight, palette, shading, and the exact token string every prompt appends.ดีเอ็นเอด้านภาพ: น้ำหนักเส้น โทนสี การลงเงา และสตริงโทเคนที่ทุกพรอมป์ต่อท้าย视觉 DNA:线条粗细、配色、阴影,以及每条提示词都会附加的固定 token 串。
write onceครั้งเดียว写一次
world.md
Where and when it happens, the tone, the rules, recurring props and motifs.เกิดที่ไหนเมื่อไร โทนเรื่อง กฎ อุปกรณ์และลวดลายที่ปรากฏซ้ำ故事发生的时间地点、基调、规则,以及反复出现的道具与母题。
write onceครั้งเดียว写一次
story.md
Logline, the arc, and the ordered list of episodes/beats to be produced.เรื่องย่อหนึ่งบรรทัด เส้นเรื่อง และลำดับตอน/จังหวะที่จะผลิต一句话梗概、故事弧线,以及按顺序排列的剧集/节拍清单。
per characterต่อตัวละคร每个角色
characters/*.md
A character sheet: name, age, look tokens (locked!), personality, voice.ใบประวัติตัวละคร: ชื่อ อายุ โทเคนหน้าตา (ล็อกไว้!) นิสัย เสียง角色设定表:姓名、年龄、外观 token(锁定!)、性格、声音。
write onceครั้งเดียว写一次
locations.md
Index of every place and which angles/lighting you've captured for it.ดัชนีของทุกสถานที่ และมุม/แสงที่คุณเก็บไว้แล้ว每个地点的索引,以及你已拍下的角度/灯光。
per shotต่อช็อต每个镜头
scenes/scene_NN.md
One shot: which characters, which location+angle, action, dialogue, camera, motion.หนึ่งช็อต: ตัวละครไหน สถานที่+มุมไหน แอ็กชัน บทพูด กล้อง การเคลื่อนไหว一个镜头:哪些角色、哪个地点+角度、动作、对白、镜头、运动。
style.md — the look, defined oncestyle.md — กำหนดหน้าตาครั้งเดียวstyle.md — 一次定义全局外观
This is the single most leveraged file. The render_tokens line gets pasted into every still prompt, so every frame inherits the same look automatically.
# Style — "Lanna Storybook"look: flat color, kawaii, clean thick lineart, soft cel shading
palette: warm — teal, cream, marigold yellow, golden-hour light
mood: gentle, cozy, hopeful
render_tokens:"kawaii, flat color, clean thick lineart, soft cel shading, storybook, masterpiece, best quality"negative:"realistic, photo, 3d, text, watermark, blurry, bad anatomy, extra fingers"model: animagine-xl-3.1 # SDXL anime, runs on the Spark
characters/ploy.md — a character sheetcharacters/ploy.md — ใบประวัติตัวละครcharacters/ploy.md — 一张角色设定表
The look_tokens field is sacred. Copy it verbatim into every prompt featuring this character and she stays recognizable across hundreds of shots. Change one word and she drifts.
# Ploy — เด็กหญิงพลอยage: 8
role: curious village girl, our hero
voice: bright, quick, giggly # maps to a TTS voice laterlook_tokens:"1girl, child, 8 years old, cheerful thai girl, round friendly face, big sparkling dark eyes, short black bob hair, small yellow frangipani flower hairpin, teal lanna blouse with cream trim"refs:
- characters/ploy_turnaround.png
- characters/ploy_expressions.png
scenes/scene_01.md — one shot, one filescenes/scene_01.md — หนึ่งช็อต หนึ่งไฟล์scenes/scene_01.md — 一个镜头,一个文件
A scene file is pure metadata. It names references instead of repeating descriptions — so it stays short and the look/character can't drift out of sync with the bible.
The scene says cast: [ploy], not the 40-word look description. The assembler looks up ploy.md and pastes the locked tokens. Update Ploy's hairpin once in her sheet and every scene gets it — no find-and-replace across 200 files.
Reference images — the ground truthภาพอ้างอิง — ความจริงตั้งต้น参考图 — 基准事实
Words drift; pictures don't. For each character and location you generate a small set of reference images from multiple angles, pick the best, and lock them. Those become the anchor every future shot is matched against (via image-to-image, IP-Adapter, or just as the seed frame for video).
A place isn't one picture. Capture the establishing wide, an interior, maybe a dusk variant — so any scene set here already has a matching backdrop instead of a fresh, inconsistent guess.
village_lane_wide.png — establishing exteriorภายนอกเปิดฉาก交代环境的外景house_interior.png — same world, second angleโลกเดียวกัน มุมที่สอง同一个世界,第二个角度
Localize on purposeจงตั้งใจให้เข้ากับท้องถิ่น刻意本地化
These backgrounds are deliberately Chiang Mai / Lanna — teak houses, carved gables, Doi Suthep on the horizon. Baking the setting into world.md and the location refs means every episode looks like your place, not generic anime.
How text + images become videoข้อความ + ภาพ กลายเป็นวิดีโอได้อย่างไร文字+图像如何变成视频
Here's the move that ties it all together. A scene file plus the bible's references get assembled into one still prompt → that still is rendered → the still becomes the first frame a video model animates. The reference layer feeds both halves.
Wan 2.2 image-to-video → a 5s clip that starts from that exact frameWan 2.2 image-to-video → คลิป 5 วิที่เริ่มจากเฟรมนั้นพอดีWan 2.2 图生视频 → 一段从该帧开始的 5 秒片段
The composed still below is scene 01's seed frame — Ploy, on-model, standing in the location ref, ready to be animated into her wave:
scene_01 — character ref + location ref + action, composed → feeds Wan 2.2 i2v.ภาพตัวละคร + ภาพสถานที่ + แอ็กชัน ประกอบกัน → ป้อนเข้า Wan 2.2 i2v角色参考 + 场景参考 + 动作,组装后 → 喂给 Wan 2.2 图生视频。
Two ways references travel into a renderสองทางที่ภาพอ้างอิงเดินเข้าสู่การเรนเดอร์参考进入渲染的两条路径
As text: the locked look_tokens go straight into the prompt. As pixels: the turnaround / location PNG is fed image-to-image or as the i2v first frame, so the model copies the actual drawing, not your description of it. Most pipelines use both.
style · world · story · characters · locations + reference imagesstyle · world · story · characters · locations + ภาพอ้างอิงstyle · world · story · characters · locations + 参考图
human · onceคน · ครั้งเดียว人 · 一次
✂️
Split story into scene_NN.mdแบ่งเรื่องเป็น scene_NN.md把故事拆成 scene_NN.md
one shot per file — the only per-episode writingหนึ่งช็อตต่อไฟล์ — งานเขียนเดียวต่อตอน一镜头一文件——每集唯一要写的东西
human · per epคน · ต่อตอน人 · 每集
🧩
Assemble each promptประกอบแต่ละพรอมป์组装每条提示词
read scene + referenced sheets → one stringอ่านฉาก + ใบที่อ้างถึง → สตริงเดียว读取场景 + 被引用的设定表 → 一个字符串
scriptสคริปต์脚本
🖼️
Render still → animate clipเรนเดอร์ภาพนิ่ง → ทำคลิปเคลื่อนไหว渲染静帧 → 生成动态片段
animagine-xl, then Wan 2.2 i2v on the Sparkanimagine-xl แล้วต่อด้วย Wan 2.2 i2v บน Sparkanimagine-xl,再用 Spark 上的 Wan 2.2 图生视频
scriptสคริปต์脚本
🔊
Voice + supersเสียงพากย์ + ซับ配音 + 字幕
TTS from dialogue:, bilingual subtitles via ffmpegTTS จาก dialogue:, ซับสองภาษาผ่าน ffmpeg由 dialogue: 生成 TTS,用 ffmpeg 烧录双语字幕
scriptสคริปต์脚本
🎞️
Stitch the episodeต่อเป็นตอน拼接成一集
concat clips in scene order, mux audio, encodeต่อคลิปตามลำดับฉาก รวมเสียง เข้ารหัส按场景顺序拼接片段、混音、编码
scriptสคริปต์脚本
The four script stages don't need you. In pseudocode the whole back half is a for loop over the scene files:
สี่ขั้นตอน สคริปต์ ไม่ต้องใช้คุณเลย ในรูปซูโดโค้ด ครึ่งหลังทั้งหมดคือลูป for วนไฟล์ฉาก:
那四个 脚本 阶段不需要你。用伪代码看,后半段整个就是对场景文件的一个 for 循环:
bible = load_all("style.md", "world.md", "characters/", "locations/")
clips = []
for scene in sorted(glob("scenes/scene_*.md")):
prompt = assemble(scene, bible) # tokens + action + style
still = render_still(prompt, bible.model) # animagine-xl, Spark
clip = animate(still, scene.motion) # Wan 2.2 i2v, Spark
voice = tts(scene.dialogue, bible.cast_voices)
clips.append(mux(clip, voice, subtitles(scene.dialogue)))
episode = stitch(clips) # concat in order, encode
The leverageจุดที่ได้เปรียบ杠杆所在
Adding episode 7 isn't "make a cartoon from scratch." It's: write a few scene_NN.md files and run the loop. The expensive, judgment-heavy work — the look, the cast, the world — was paid for once, at the start. Everything after compounds on it.
"Almost automatic" is the right phrase, not "automatic." Models still miss — a bad hand, a drifted face, a clip that ignores the motion prompt. The loop gets you a full draft cheaply; you still spot-fix shots by re-rolling a seed or nudging a scene file. Front-loading the bible is what makes those fixes local instead of cascading.
Copy-paste templates — a blank form + a filled example for every fileเทมเพลตคัดลอกวาง — ฟอร์มเปล่า + ตัวอย่างที่กรอกแล้ว สำหรับทุกไฟล์复制粘贴模板 — 每个文件都有一份空白表单+一个填好的示例
Here is the whole bible as fill-in-the-blank forms. For each file: copy the blank on the left into your project, then use the filled example on the right as the answer key. Replace every <…> placeholder and delete the angle brackets.
# Style — "<your series look name>"look:<lineart + shading words>palette:<3–5 colours + the lighting>mood:<2–3 adjectives>render_tokens:"<tokens appended to EVERY still prompt>"negative:"<things to never render>"model:<image model># e.g. animagine-xl-3.1
style.md filled exampleตัวอย่างที่กรอก填好示例
# Style — "Lanna Storybook"look: flat color, kawaii, clean thick lineart, soft cel shading
palette: warm — teal, cream, marigold yellow, golden-hour light
mood: gentle, cozy, hopeful
render_tokens:"kawaii, flat color, clean thick lineart, soft cel shading, storybook, masterpiece, best quality"negative:"realistic, photo, 3d, text, watermark, blurry, bad anatomy, extra fingers"model: animagine-xl-3.1 # SDXL anime, on the Spark
world.md — the settingworld.md — ฉากของเรื่องworld.md — 设定世界
world.md blank formฟอร์มเปล่า空白表单
# World — "<your world name>"setting:<where + when it happens>region:<real-place anchor for localizing the look>tone:<the feel of this world>rules:<what's true here / what can't happen>props:<recurring objects + motifs>palette_notes:<how the world tints the style>
world.md filled exampleตัวอย่างที่กรอก填好示例
# World — "Ban Doi, a Lanna village"setting: a small northern Thai village, present day, endless golden afternoons
region: Chiang Mai / Lanna — teak houses, carved gables, Doi Suthep on the skyline
tone: gentle slice-of-life; small adventures, no real danger
rules: everyday magic is fine (a talking cat); nothing scary or violent
props: paper lanterns, frangipani flowers, a red songthaew, sticky-rice baskets
palette_notes: warm golden-hour light tints every exterior
# Story — "<your series title>"logline:<one sentence: who wants what, against what>arc:<the season-long change, in a line>audience:<who it's for>episodes:
- 01: <title> — <one-line beat>
- 02: <title> — <one-line beat>
- 03: …
story.md filled exampleตัวอย่างที่กรอก填好示例
# Story — "Ploy's Little Village"logline: An 8-year-old invites the world to visit her Lanna village, one tiny adventure at a time.
arc: Ploy learns her ordinary home is full of wonders worth sharing.
audience: kids 5–9 + Thai / English language learners
episodes:
- 01: Hello! — Ploy welcomes us and waves from the lane
- 02: The Lantern — Ploy and Grandma make a lantern for Loy Krathong
- 03: The Cat Who Talks — a stray cat leads Ploy to a hidden garden
locations.md — the place indexlocations.md — ดัชนีสถานที่locations.md — 地点索引
# Locations — indexvillage_lane:desc: the main dirt lane, teak houses either side
angles: [wide, dusk] # → locations/village_lane_wide.png, _dusk.pnghouse:desc: Ploy's wooden Lanna home
angles: [interior] # → locations/house_interior.pnghidden_garden:desc: a walled garden full of frangipani
angles: [wide, detail]
characters/<name>.md — a character sheetcharacters/<name>.md — ใบประวัติตัวละครcharacters/<name>.md — 角色设定表
characters/<name>.md blank formฟอร์มเปล่า空白表单
# <Name> — <name in Thai>age:<number>role:<who they are in the story>voice:<2–3 words># maps to a TTS voice laterlook_tokens:"<comma tokens — LOCK these, copy verbatim into every prompt with this character>"refs:
- characters/<name>_turnaround.png
- characters/<name>_expressions.png
# Ploy — เด็กหญิงพลอยage: 8
role: curious village girl, our hero
voice: bright, quick, giggly # maps to a TTS voice laterlook_tokens:"1girl, child, 8 years old, cheerful thai girl, round friendly face, big sparkling dark eyes, short black bob hair, small yellow frangipani flower hairpin, teal lanna blouse with cream trim"refs:
- characters/ploy_turnaround.png
- characters/ploy_expressions.png
scenes/scene_NN.md — one shotscenes/scene_NN.md — หนึ่งช็อตscenes/scene_NN.md — 一个镜头
scenes/scene_NN.md blank formฟอร์มเปล่า空白表单
# Scene NN — <one-line shot title>location:<location_id># → locations/<id>_<angle>.pngcast:[<character_ids>]# → pulls each <id>.look_tokensaction:<what happens in this shot>camera:<shot size, angle, lighting>dialogue:
- who:<character_id>th:"<Thai line>"en:"<English line>"motion:<how it moves, for image-to-video>seconds:<clip length>
# Scene 01 — Ploy says hellolocation: village_lane_wide # → locations/village_lane_wide.pngcast: [ploy] # → pulls ploy.look_tokensaction: Ploy stands in the lane and waves hello, smiling
camera: wide, eye-level, golden hour
dialogue:
- who: ploy
th: "สวัสดีค่ะ! มาเที่ยวบ้านเราสิ"
en: "Hi there! Come visit my village!"
motion: she waves, hair sways gently, camera slowly pushes in
seconds: 5
Fill orderลำดับการกรอก填写顺序
Top to bottom is also chronological: style → world → story → one characters/*.md per cast member → locations → then a scenes/scene_NN.md per shot. The first five are the write-once bible; only the scene form repeats per shot.
จากบนลงล่างคือลำดับเวลาด้วย: style → world → story → characters/*.md หนึ่งไฟล์ต่อตัวละคร → locations → แล้วจึง scenes/scene_NN.md ต่อช็อต ห้าอย่างแรกคือคัมภีร์เขียนครั้งเดียว มีแค่ฟอร์มฉากที่ทำซ้ำต่อช็อต
从上到下也是时间顺序:style → world → story → 每个角色一份 characters/*.md → locations → 然后每个镜头一份 scenes/scene_NN.md。前五个是写一次的设定集;只有场景表单每镜头重复。
Start hereเริ่มต้นตรงนี้从这里开始
Create the folder tree above — empty files are fine to start.
The example stills here were generated locally on the DGX Spark with animagine-xl-3.1 — no paid API. The same Spark runs the Wan 2.2 image-to-video step. See How We Made the Hero Video for a real end-to-end build.
ภาพนิ่งตัวอย่างในหน้านี้สร้างบนเครื่อง DGX Spark ด้วย animagine-xl-3.1 — ไม่มี API เสียเงิน เครื่อง Spark เดียวกันรันขั้นตอน Wan 2.2 image-to-video ดู How We Made the Hero Video สำหรับการสร้างจริงตั้งแต่ต้นจนจบ
本页的示例静帧是在 DGX Spark 本地用 animagine-xl-3.1 生成的——没有付费 API。同一台 Spark 跑 Wan 2.2 图生视频这一步。完整的端到端实例见 How We Made the Hero Video。