Crayon Picture Book Animator

Crayon storybook

by edenfunf · MIT license · ★ 3,630 on GitHub

Crayon storybook cover

Make warm children's picture-book animations (MP4) drawn in crayon, coloured pencil and pastel on cream drawing paper — waxy crayon scribble fills broken by paper tooth, coloured-pencil outlines, slow 8 fps line boil, page-turn…

---
name: crayon-storybook
description: Make warm children's picture-book animations (MP4) drawn in crayon, coloured pencil and pastel on cream drawing paper — waxy crayon scribble fills broken by paper tooth, coloured-pencil outlines, slow 8 fps line boil, page-turn transitions, picture-book page framing and hand-lettered CJK storybook captions. p5.js + p5.brush rendered frame by frame in headless Chrome, encoded with ffmpeg. Use when a reference video or brief calls for a crayon / colored-pencil / pastel / kids' drawing / picture-book / bedtime-story / 繪本 / 蠟筆 / 色鉛筆 / 童書 look, or when the video-clone router picks the crayon-storybook style.
---

# Crayon storybook

A drawing engine for ReelMimic. Every frame is a pure function of time `t`: `studio.html` loads p5.js + p5.brush, the
crayon look library, the cast and your scene files; each shot draws the whole 1920×1080 frame; `render.mjs` renders
contact sheets, strips and crops for review, or all frames in parallel, and ffmpeg encodes the MP4.

**Provenance.** The runtime (`template/src/core.js`, `timeline.js`, `render.mjs`, `studio.html`, the render contract and
helpers: `paint`, `inkLine`, camera, `shots`, `glow`, `jump`/`take`/`spring`, `boilSeed`…) derives from the
**painted-animation** skill (ClaudeAnimationBase, MIT © John Heibel / tuzhechen2005 — see `template/LICENSE`). The
look (`crayon.js`), the characters (`cast.js`), the page turn, the page finish and the captions are this engine's own.

## Workflow

Overview

A drawing engine for ReelMimic. Every frame is a pure function of time t: studio.html loads p5.js + p5.brush, the crayon look library, the cast and your scene files; each shot draws the whole 1920×1080 frame; render.mjs renders contact sheets, strips and crops for review, or all frames in parallel, and ffmpeg encodes the MP4.

Manual install (npx, ZIP)
Claude Codenpx skills add edenfunf/reelmimic --skill crayon-storybook -g -a claude-code
Claude Code (degit)npx degit edenfunf/reelmimic/.claude/skills/crayon-storybook#main ~/.claude/skills/crayon-storybook
Claude.ai / desktopZip the folder and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md6.7 KB
Read SKILL.md here
edenfunf/main1 file shown
SKILL.md
Show the full text81 lines
crayon-storybook/SKILL.md81 lines · 6.7 KB

Crayon storybook

A drawing engine for ReelMimic. Every frame is a pure function of time t: studio.html loads p5.js + p5.brush, the crayon look library, the cast and your scene files; each shot draws the whole 1920×1080 frame; render.mjs renders contact sheets, strips and crops for review, or all frames in parallel, and ffmpeg encodes the MP4.

Provenance. The runtime (template/src/core.js, timeline.js, render.mjs, studio.html, the render contract and helpers: paint, inkLine, camera, shots, glow, jump/take/spring, boilSeed…) derives from the painted-animation skill (ClaudeAnimationBase, MIT © John Heibel / tuzhechen2005 — see template/LICENSE). The look (crayon.js), the characters (cast.js), the page turn, the page finish and the captions are this engine's own.

Workflow

  1. Scaffold — bash .claude/skills/crayon-storybook/scripts/new_project.sh <project-dir> (add --keep-demo to keep the example). It copies the template, runs npm install (which also writes the patched p5.brush build, see gotchas) and checks node / ffmpeg / Chrome. Then read GUIDE.md in full and look at docs/demo-sheet.jpg and docs/cast.jpg with Read.
  2. Storyboard in writing: shots, reads (what the viewer must understand, when), transitions, captions.
  3. Build — src/config.js (duration, bpm, fps: 24); one IIFE file per shot/scene in src/scenes/, ending with shots([...]); add its <script> to studio.html. Captions: captions([[t0, t1, '文字', { pos }]]) once.
  4. Look, fix, look again (from the project dir):
    node render.mjs --sheet=0.5,1.5,2.5,3.5 --cols=4 --w=480 --out=out/check/a.jpg
    node render.mjs --strip=2.0:2.6 --cols=6 --w=320 --out=out/check/strip.jpg
    node render.mjs --sheet=2.3 --cols=1 --crop=600,200,900,700 --w=900 --out=out/check/face.jpg
    
    Open every image with Read. At least a sheet per shot, a strip per key action and per transition, a crop per face.
  5. Render — node render.mjs --frames --workers=4 && node render.mjs --encode --out=out/video.mp4 [--audio=…].

API in one screen

area calls
fills `colorIn(pts, { col, fill: 'scribble'
lines crayonLine, pencilLine, pastelLine, sketchLine, inkLine(pts, sw, col, brush) — brushes crayon, crayonFine, cpen, pastel, chalk, graphite
shapes ellPts, rectPts, rrPts, starPts, heartPts, through, ribbon (core)
scenery sky, sun, cloud, hill/hillY, ground, tufts, tree, flower, house, paperWash
props apple, leafProp, starProp, heartProp, balloon; emotes emote(kind, x, y, s, k, age)
cast lulu(x, y, u, o), kuri(x, y, u, o) → { head, top, handL, handR, feet }; feel, emotions, walkCycle, pose
motion seg, kf, ease*, backOut, spring, ring, jump, take, stroll, arcPt, onTwos, pulse, shakeXY
camera camBegin(cx, cy, zoom, rot) … camEnd(), toScreen
staging shots([[t0, fn], [t1, fn, { turn: 1.0 }]]) (page turn), bookPage(k), vignette(k), tooth(k), crayonWipe(p), iris, flash, glow
text captions(list) (storybook captions via window.overlayHook), letter() for words inside the picture

Rules that matter most

  1. Crayon medium only. Colour shapes in with colorIn (pale base + crayon scribble/hatch + coloured-pencil outline); lines with the crayon/pencil brushes. No plain p5 rect/ellipse/fill, no gradients, no 3D. Turns go through the drawn key views (front, q, side, back).
  2. Pure functions of t. No Math.random(), no state between frames. hash() / rnd(key) for stable randomness; jit() only for boil. Call boilSeed(key) before each separate background element/prop.
  3. Characters come from cast.js only. Scenes pass poses (aR, bR, view, walk, dy, sq, hair, holdR…) — they never draw a character's parts themselves. New characters go in cast.js (or one file each).
  4. Big and legible. Lulu u ≈ 30–45 in medium shots (≈ 11u tall), Kuri u ≈ 26–36. Captions ≥ 64 px. Keep the caption band (bottom ~200 px, or pos: 'top') free of story-critical action.
  5. Alive and acted. Moods change through emotions() (anticipation squint → take → settle); actions have anticipation → action → follow-through (jump, spring, hair); something happens in every shot.
  6. A transition at every seam: page turn ({ turn }), crayon wipe, iris, fade from/to paper.

Engine gotchas

  • Patched p5.brush. studio.html loads node_modules/p5.brush/dist/p5.brush.crayon.js, written by patch_brush.mjs on npm install. Stock p5.brush darkens pigment where overlapping stamps saturate (right for ink, wrong for wax): butter-yellow turned mustard. If that file is missing, run node patch_brush.mjs.
  • Cost = number of colour changes + stroke area. Each colorIn is ~3 brush passes; p5.brush composites a mask per colour change. Keep big background shapes sparse (hill/ground already use wide gaps), don't scribble far off-screen. Typical: 150–250 ms/frame for a wide shot, ~350 ms for a busy medium shot with two characters and the page border, ~0.7–1 s during a page turn (two pages are drawn).
  • Page turn: the previous shot keeps being called with lt > dur for turn seconds — let its motion settle.
  • Don't name globals after p5's (line, text, color, scale, shape…): the page never gets ready.
  • A NaN in a point list throws Failed to construct 'OffscreenCanvas'. ** after a unary minus is a syntax error.
  • Strokes far from the origin under zoom ≳ 2 collapse (p5.brush); paint/inkLine/colorIn draw around each shape's centre, which avoids it for normal sizes.
  • Google Fonts load over the network at page load; if a render times out on navigation, just re-run it.
  • src/karaoke.js (from painted-animation) still works for lyric videos; add its <script> if needed.
1---
2name: crayon-storybook
3description: Make warm children's picture-book animations (MP4) drawn in crayon, coloured pencil and pastel on cream drawing paper — waxy crayon scribble fills broken by paper tooth, coloured-pencil outlines, slow 8 fps line boil, page-turn transitions, picture-book page framing and hand-lettered CJK storybook captions. p5.js + p5.brush rendered frame by frame in headless Chrome, encoded with ffmpeg. Use when a reference video or brief calls for a crayon / colored-pencil / pastel / kids' drawing / picture-book / bedtime-story / 繪本 / 蠟筆 / 色鉛筆 / 童書 look, or when the video-clone router picks the crayon-storybook style.
4---
5 
6# Crayon storybook
7 
8A drawing engine for ReelMimic. Every frame is a pure function of time `t`: `studio.html` loads p5.js + p5.brush, the
9crayon look library, the cast and your scene files; each shot draws the whole 1920×1080 frame; `render.mjs` renders
10contact sheets, strips and crops for review, or all frames in parallel, and ffmpeg encodes the MP4.
11 
12**Provenance.** The runtime (`template/src/core.js`, `timeline.js`, `render.mjs`, `studio.html`, the render contract and
13helpers: `paint`, `inkLine`, camera, `shots`, `glow`, `jump`/`take`/`spring`, `boilSeed`…) derives from the
14**painted-animation** skill (ClaudeAnimationBase, MIT © John Heibel / tuzhechen2005 — see `template/LICENSE`). The
15look (`crayon.js`), the characters (`cast.js`), the page turn, the page finish and the captions are this engine's own.
16 
17## Workflow
18 
191. **Scaffold** — `bash .claude/skills/crayon-storybook/scripts/new_project.sh <project-dir>` (add `--keep-demo` to keep
20 the example). It copies the template, runs `npm install` (which also writes the patched p5.brush build, see
21 gotchas) and checks node / ffmpeg / Chrome. Then **read [GUIDE.md](GUIDE.md) in full** and look at
22 `docs/demo-sheet.jpg` and `docs/cast.jpg` with Read.
232. **Storyboard** in writing: shots, reads (what the viewer must understand, when), transitions, captions.
243. **Build** — `src/config.js` (`duration`, `bpm`, `fps: 24`); one IIFE file per shot/scene in `src/scenes/`, ending with
25 `shots([...])`; add its `<script>` to `studio.html`. Captions: `captions([[t0, t1, '文字', { pos }]])` once.
264. **Look, fix, look again** (from the project dir):
27 ```bash
28 node render.mjs --sheet=0.5,1.5,2.5,3.5 --cols=4 --w=480 --out=out/check/a.jpg
29 node render.mjs --strip=2.0:2.6 --cols=6 --w=320 --out=out/check/strip.jpg
30 node render.mjs --sheet=2.3 --cols=1 --crop=600,200,900,700 --w=900 --out=out/check/face.jpg
31 ```
32 Open every image with Read. At least a sheet per shot, a strip per key action and per transition, a crop per face.
335. **Render** — `node render.mjs --frames --workers=4 && node render.mjs --encode --out=out/video.mp4 [--audio=…]`.
34 
35## API in one screen
36 
37| area | calls |
38|---|---|
39| fills | `colorIn(pts, { col, fill: 'scribble'|'hatch'|'cross'|'smudge'|'flat', ang, gap, line, lw, shade })`, `scribbleFill`, `hatchFill`, `crossHatch`, `smudge`, `dab` |
40| lines | `crayonLine`, `pencilLine`, `pastelLine`, `sketchLine`, `inkLine(pts, sw, col, brush)` — brushes `crayon`, `crayonFine`, `cpen`, `pastel`, `chalk`, `graphite` |
41| shapes | `ellPts`, `rectPts`, `rrPts`, `starPts`, `heartPts`, `through`, `ribbon` (core) |
42| scenery | `sky`, `sun`, `cloud`, `hill`/`hillY`, `ground`, `tufts`, `tree`, `flower`, `house`, `paperWash` |
43| props | `apple`, `leafProp`, `starProp`, `heartProp`, `balloon`; emotes `emote(kind, x, y, s, k, age)` |
44| cast | `lulu(x, y, u, o)`, `kuri(x, y, u, o)` → `{ head, top, handL, handR, feet }`; `feel`, `emotions`, `walkCycle`, `pose` |
45| motion | `seg`, `kf`, `ease*`, `backOut`, `spring`, `ring`, `jump`, `take`, `stroll`, `arcPt`, `onTwos`, `pulse`, `shakeXY` |
46| camera | `camBegin(cx, cy, zoom, rot)` … `camEnd()`, `toScreen` |
47| staging | `shots([[t0, fn], [t1, fn, { turn: 1.0 }]])` (page turn), `bookPage(k)`, `vignette(k)`, `tooth(k)`, `crayonWipe(p)`, `iris`, `flash`, `glow` |
48| text | `captions(list)` (storybook captions via `window.overlayHook`), `letter()` for words inside the picture |
49 
50## Rules that matter most
51 
521. **Crayon medium only.** Colour shapes in with `colorIn` (pale base + crayon scribble/hatch + coloured-pencil outline);
53 lines with the crayon/pencil brushes. No plain p5 `rect/ellipse/fill`, no gradients, no 3D. Turns go through the
54 drawn key views (`front`, `q`, `side`, `back`).
552. **Pure functions of `t`.** No `Math.random()`, no state between frames. `hash()` / `rnd(key)` for stable randomness;
56 `jit()` only for boil. Call `boilSeed(key)` before each separate background element/prop.
573. **Characters come from `cast.js` only.** Scenes pass poses (`aR`, `bR`, `view`, `walk`, `dy`, `sq`, `hair`,
58 `holdR`…) — they never draw a character's parts themselves. New characters go in `cast.js` (or one file each).
594. **Big and legible.** Lulu u ≈ 30–45 in medium shots (≈ 11u tall), Kuri u ≈ 26–36. Captions ≥ 64 px. Keep the
60 caption band (bottom ~200 px, or `pos: 'top'`) free of story-critical action.
615. **Alive and acted.** Moods change through `emotions()` (anticipation squint → take → settle); actions have
62 anticipation → action → follow-through (`jump`, `spring`, `hair`); something happens in every shot.
636. **A transition at every seam**: page turn (`{ turn }`), crayon wipe, iris, fade from/to paper.
64 
65## Engine gotchas
66 
67- **Patched p5.brush.** `studio.html` loads `node_modules/p5.brush/dist/p5.brush.crayon.js`, written by
68 `patch_brush.mjs` on `npm install`. Stock p5.brush darkens pigment where overlapping stamps saturate (right for ink,
69 wrong for wax): butter-yellow turned mustard. If that file is missing, run `node patch_brush.mjs`.
70- **Cost = number of colour changes + stroke area.** Each `colorIn` is ~3 brush passes; p5.brush composites a mask per
71 colour change. Keep big background shapes sparse (`hill`/`ground` already use wide gaps), don't scribble far
72 off-screen. Typical: 150–250 ms/frame for a wide shot, ~350 ms for a busy medium shot with two characters and the
73 page border, ~0.7–1 s during a page turn (two pages are drawn).
74- **Page turn:** the previous shot keeps being called with `lt > dur` for `turn` seconds — let its motion settle.
75- **Don't name globals after p5's** (`line`, `text`, `color`, `scale`, `shape`…): the page never gets ready.
76- A `NaN` in a point list throws `Failed to construct 'OffscreenCanvas'`. `**` after a unary minus is a syntax error.
77- Strokes far from the origin under zoom ≳ 2 collapse (p5.brush); `paint/inkLine/colorIn` draw around each shape's
78 centre, which avoids it for normal sizes.
79- Google Fonts load over the network at page load; if a render times out on navigation, just re-run it.
80- `src/karaoke.js` (from painted-animation) still works for lyric videos; add its `<script>` if needed.
81 
View all files on GitHub →

Details

License
MIT
Stars on the repo
★ 3,630
Checked
Source
edenfunf/reelmimic ↗
Creator
edenfunf · 6 listings
View creator

Similar skills

See all →

More from edenfunf

SkillCel-Shaded Video Creatoredenfunf/reelmimic · by edenfunfMake Japanese TV-anime style videos (MP4) with code — cel-shaded characters with tapered line art, big detailed eyes, hair clumps with a specular band, comedic anime reactions (sweat drop, anger vein, sparkle eyes, ≥< eyes, dot eyes, tears), painted skies with cumulus clouds, school/street/classroom/rooftop sets with time-of-day palettes, speed/focus lines, impact frames, dramatic zooms, smears, sakura petals and anime subtitles (CJK). Canvas 2D rendered frame by frame in headless Chrome, encoded with ffmpeg. Use when a reference video or brief calls for anime / 動畫 / 日系動畫 / アニメ / cel-shaded / slice-of-life / school romance / shōnen-style reactions, or when the video-clone router picks the anime-cel style. 2D only; characters are original (Hina, Ren) or new ones built on the same rig.★ 3.6k GitHub starsSkillWatercolor Animation Generatoredenfunf/reelmimic · by edenfunfMake hand-painted watercolour-and-ink cartoon videos (MP4) with code — p5.js + p5.brush rendered frame by frame in headless Chrome, encoded with ffmpeg — starring Clawd or any character. Use when the user asks to make an animation, animated short, cartoon, music video, lyric video, animated GIF/loop or "a video of Clawd…", or mentions the PDoomVideo / ClaudeAnimationBase approach. Covers storyboarding, the engine API, the render-and-look review loop, music/lyric sync and splitting long videos across subagents.★ 3.6k GitHub starsSkillPaper Cutout Animation Makeredenfunf/reelmimic · by edenfunfMake paper cut-out / stop-motion style animated videos (MP4) with code — handmade construction paper, cardstock, kraft, felt and tissue pieces with scissor-cut or torn edges and soft drop shadows, photographed on a table under a warm lamp; jointed paper puppets with brass split-pin joints, moving in 12 fps steps. Canvas 2D rendered frame by frame in headless Chrome, encoded with ffmpeg. Use when a reference video or brief calls for paper craft, cut-paper, papercraft, stop-motion paper, kids' storybook collage, 剪紙 / 紙片 / 紙偶 / 定格動畫 looks, or when the video-clone router picks the paper-cutout style.★ 3.6k GitHub starsSkillCustom Video Composeredenfunf/reelmimic · by edenfunfAuthor or edit a custom HyperFrames composition when no specialized workflow fits, or when BRIEF.md sets flow: companion. Use for longer or multi-scene pieces, brand and sizzle reels, montages, static loops, static title cards, footage remixes, and freeform builds. Use motion-graphics instead for a short unnarrated motion-first unit, including an animated title. Route fresh creation through hyperframes before using this skill.★ 543 GitHub starsSkillCode Change Explaineredenfunf/reelmimic · by edenfunfTurn a GitHub pull request (a PR URL, owner/repo#N, or 'this PR' in a checked-out repo) into a code-change explainer video — changelog, feature reveal, fix, or refactor walkthrough built from the diff, commits, and files: the input is a code change, not a website. Not a product promo (/product-launch-video) or a no-PR topic explainer (/faceless-explainer). Unclear → /hyperframes.★ 543 GitHub stars