Marker on Paper — our demo

One example among many. Don't reuse its story, arc, shots, props or timings.

Demo: How Far Can You See? 《你能看多遠?》 (52 s) · marker-paper.mp4 · marker-paper.srt · source in demo/

An English narrator asks how far the horizon is from a beach; three sheets of white paper answer it with a black, a blue and a red marker. Subtitles carry each line in Chinese and English. The numbers and their sources are in demo/FACTS.md.

Story & structure

Hook: stand on a beach — how far away is the horizon? Middle: your line of sight grazes the Earth at a right angle, so it is a right triangle; h² is tiny, drop it; d ≈ √(2Rh) ≈ 4.5 km. Landing on a contrast: climb a hundred times higher (160 m) and you see only ten times farther (45 km); from a plane ten kilometres up, about 357 km. The last stroke circles the rule. Each sheet brings one new thing: the question, the answer, the contrast. Red goes further every time: a question mark, a term, a circled number, a line across the whole sheet, the circled rule.

Native moves spent: the unknown in red (sheet ①), push through a shape (the right-angle mark, ① → ②), same colour same quantity (the algebra), scribble it out (h²), the peel (② → ③), bars to scale with one a dot (③), the last red circle.

Shots

# Time Shot Camera Native move / note
1 0–3.2 one sweep draws the Earth's arc, 65 hatch flicks, the figure, the line of sight, a ship with only its sail above the horizon, the right-angle mark close 1.5×, following the pen left to right
2 3.2–3.95 — pull back to the whole sheet room for the question
3 3.85–6.55 "How far away is the horizon?" written as it is spoken, 地平線有多遠?, page ① locked
4 7.45–10.4 blue h = 1.6 m, two dashed radii, R = 6,371 km; red double arrow and d = ? from 8.1 s lean in to 1.7× on h, R and d (title and page number wholly out, after they have been read) the unknown in red
5 11.6–12.35 the right-angle mark fills the frame push through the mark to 7×, accelerating push through a shape
6 12.35–13.25 sheet ②: the same mark, same place, size and line weight, alone on white pull out to the whole sheet match cut
7 13.25–19.8 Earth arc, figure, red line of sight d grazing it, "Look closer", the pen goes over the right angle again (double ink), blue R, R, h locked
8 18.4–20.7 (R + h)² = R² + d² in the drawing's colours from 19.8 s follow the pen into the algebra, 1.5× same colour, same quantity
9 20.7–25.0 d² = 2Rh + h², h² scribbled out with "tiny"; red d ≈ √(2Rh); the numbers put in 1.5× scribble it out
10 26.2–29.0 ≈ 4.5 km in red, two underlines, the first red circle lean in to 1.62×
11 29.0–29.8 the corner lifts, the fold sweeps, the sheet is pulled off — the peel
12 29.8–33.55 "What if you climb?", 爬高一點呢?, page ③; the first two rows begin locked
13 31.9–36.2 figure 1.6 m → a red dot 4.5 km; tower 160 m (blue ×100) → red bar 45 km (red ×10) from 33.55 s lean in to 1.8× on the two rows bars to scale
14 36.2–37.2 the long empty line waiting on the right pull back, almost silent scale reveal
15 37.2–43.9 plane, 10 km; one red stroke across the sheet (1.2 s); ≈ 357 km; "bars drawn to scale" locked
16 43.9–46.85 d ≈ √(2Rh) written top right, the last red circle, 高四倍,遠兩倍 lean in to 2× on the rule (title wholly out) the last red circle
17 46.85–47.6 the whole sheet: question, three rows, circled rule pull back to the whole sheet
18 47.6–52.0 end card written in the empty corner (below) locked

Narration and subtitles

English, Kokoro bm_george at speed 0.84 (≈ 2.5 words/s); numbers spelled out in the voice text (demo/vo/lines.json), digits in the subtitles. Every line passes core/tts/asr_check.py.

Start (s) English 中文字幕
0.30 Stand on a beach, and look out to sea. 站在海邊,望向大海。
3.95 How far away is the horizon? 地平線離你有多遠?
7.45 Blue is what we know. Red is what we want. 藍色是已知的,紅色是要求的。
13.20 Your line of sight just grazes the Earth, at a right angle. 視線剛好擦過地球,和半徑成直角。
19.70 h² is tiny, so we drop it. h² 小到可以忽略,劃掉它。
23.40 From 1.6 m up: about 4.5 km. 眼高 1.6 米:大約 4.5 公里。
29.90 Now, climb 100 times higher. 現在,爬高 100 倍。
33.15 You see only 10 times farther. 你只能多看遠 10 倍。
37.20 From a plane, 10 km up: about 357 km. 從 10 公里高的飛機上看:大約 357 公里。
44.05 The view grows only with the square root of your height. 視野只隨高度的平方根增長。

Score structure

100 bpm (beat 0.6 s, bar 2.4 s), D dorian resolving to F major. Pizzicato double bass walks under the drawing; staccato clarinet and bassoon carry a "thinking" figure; shaker and claves keep a light pulse; harp and glockenspiel only where red lands.

Palette & props

Paper #FAF9F5; black #1B1C20; red #E23B2E; blue #2456D6; peel back #E2E0D9 → #F7F6F2. Props are drawn in the same marker: a stick figure with a cap shading its eyes, a sailboat, a lattice tower, a small plane. The Earth's curvature is exaggerated on sheets ① and ②; the bars on sheet ③ are to scale (1150 px = 357 km).

End card

Written in the empty bottom-right corner of sheet ③ with the black marker, 47.62–48.35 s, held to 52.0 s (3.65 s whole): a short rule, How far can you see?, 你能看多遠?, Marker on Paper 馬克筆白紙速寫, and LemoLab × Claude Opus 5.5 (Kalam Bold 34 px). The "LemoLab × Claude Opus 5.5" sign-off belongs to this library's demo only; a user's film carries no LemoLab credit and no copy of this card.

Build notes

sh styles/marker-paper/demo/build.sh              # the whole film → marker-paper.mp4, marker-paper.srt, poster.jpg, demo/stills/styleframe.jpg
sh styles/marker-paper/demo/build.sh 0 12 out/cut.mp4   # any stretch of the timeline
node core/render/still.mjs styles/marker-paper/demo 27.5 --q nosubs=1   # one moment, without the subtitle slip
File What it is
demo/index.html the page; loads film.js
demo/film.js three sheets on one timeline: every pen action and its time, camera keys, the push-through match cut, the peel, the subtitle slip, window.EV (pen-downs, peel, cues, voice) and window.TEXTS
demo/pen.js the marker brush, ink-density layers, glyph-skeleton handwriting, paper, compositor
demo/glyphs.json, demo/tools/skeleton.py, demo/tools/zh_chars.txt glyph centre lines for Kalam Bold / Regular and LXGW Marker Gothic, the script that makes them, and every Chinese character the film writes or subtitles
demo/tools/subset_film.py the LXGW Marker Gothic subset (fonts/LXGWMarkerGothic-film.ttf)
demo/vo/lines.json, demo/vo/dur.json, demo/vo/words.json the narration text (and the transcript each line must match), durations, word times
demo/mix.py voice, felt-marker foley from the pen-down events, peel and push sounds, the score; balance by RMS
demo/tools/srt.mjs subtitle cues from the page → out/cues.json → core/render/srt.py
demo/build.sh fonts (downloaded when missing), subset, skeletons, voice (when missing), events, picture, sound, master, subtitles, poster
demo/CREDITS, demo/FACTS.md fonts, voice, samples; every number with its source

On a fresh clone build.sh first fetches the voice model and the two sample packs the score uses (sh tools/fetch.sh voice, sh tools/fetch.sh instruments vsco2ce, sh tools/fetch.sh instruments vcsl). Order: fonts → subset → skeletons → voice + speech check → events.mjs → video.mjs (2 workers ≈ 4 min) → mix.py → mux.sh → subtitles → poster. The fonts, the voice WAVs and the renders stay local; build.sh makes them again. Review: a contact sheet every 1.5 s, a speech-to-text pass over the finished film against the subtitles, ebur128, blackdetect, core/render/readcheck.mjs.

Pitfalls tied to this demo: every lean-in starts only after the texts it pushes out have had their reading time (readcheck.mjs measures a text until it leaves the frame); the push-through needs the sheet-② mark built in sheet ①'s turn (the geometry is rotated by the line-of-sight angle) and its size × zoom equal on both sides of the cut (28 px × 7 = 64 px × 3.06); the arc on sheet ② must stop short of the algebra column.