Neon Tubes — our demo
One example among many. Don't reuse its story, arc, shots, props or timings.
Demo: Midnight Snack 《夜宵》 (48.0 s) · neon-tubes.mp4 · source in demo/
A rainy night street of neon signs, told without a word. A turquoise neon cat wakes on the sign of an ice café, sees the goldfish on the sign of a goldfish shop at the end of the street, and goes for it, lighting every sign it lands on. Its pounce cracks the fishbowl: the water drains a level at a time and the fish fades. The cat takes the fish in its mouth, runs it home through the rain and drops it into the goblet of iced water on its own sign, where the fish strikes back to life. At closing time the street goes dark one sign at a time until only the goblet, the fish and the sleeping cat are left in a puddle. The shop names, street and times are invented; what is real is the medium, sourced in demo/FACTS.md.
Story & structure
Logline: a neon cat goes out for a midnight snack, breaks the goldfish's bowl, and carries the fish home to save it.
Arc: waking (an electrode fires in the cat's eye, light runs through its outline, its home sign strikes after it) → want (a whip pan down the dark street to the goldfish sign striking on the downbeat; a match cut from the round bowl to the cat's round eye) → the journey (each sign strikes as the cat lands: a clock it swats five hours forward, which brings the rain; a hanging hotel box; an arrow chaser that carries it like a conveyor; the karaoke board) → the mistake (two paws into the bowl, a wiggle, a pounce; the crack, three water lines going out one level at a time, the fish darker every beat; ears back, half a step back, a look, one silent beat) → the run home (chorus: down to the street, along the base of the wall with its twin in the puddles, over the alley, a wide where the street flashes after it, up the café's facade) → the goblet (the fish goes in and goes out, then strikes back on the heaviest beat of the film) → closing time (signs off one per beat, the cat curls up and its eye goes out, the last sign in a still puddle) → the end card, with one eye striking open at the fish.
Native moves spent: strike (eye, home sign, every landing, the revival, the last glance), frame-switched character (39 cat poses, 9 fish frames), strike in sequence (the journey), chaser (the arrow conveyor, bubbles), alternate circuits (the fish's tail, the microphone, window frames), crack and drain (the bowl), crane to puddle level and puddle-level chase (the run home), rise from the reflection (the climb), one sign left (the ending).
Shots
| # | Time | Shot | Camera | Native move / note |
|---|---|---|---|---|
| 1 | 0.0–3.75 | Cold milky glass of the cat on the 冰室 sign; the eye strikes at 0.25; light runs through the outline (0.6–1.35), whiskers and tail flash on; the goblet, its water, ice, straw, 冰室 and ICE CAFE strike after it (1.6–2.3); yawn, stretch, sit up and look right (3.25) | macro on the eye (eye height = subject height), pull back to a medium | strike; light running through a tube |
| 2 | 3.75–7.0 | Whip pan 16 m down the dark street; the 金魚 GOLDFISH sign strikes on the downbeat (4.0); the fish's tail swaps circuits each beat, bubbles chase up in 8ths; the sign holds 2.6 s | whip pan with motion blur, slow push | match cut at 7.0: round bowl → round eye at the same screen point |
| 3 | 7.0–8.0 | The eye from round to slit; pull back; crouch and a two-frame wiggle in 16ths; push-off | macro, fast pull back | alternate circuits (eye) |
| 4 | 8.0–15.5 | Lands on the neon clock (it warms violet → blue), swats the minute hand (18:05 → 23:40), rain starts (9.6); jumps to the hanging hotel box 2 m in front of the wall (it grows toward the lens); drops onto the arrow, which chases in 16ths and carries it; flung past the microphone onto the karaoke board, which strikes character by character; a six-frame leap over the dark alley onto the goldfish sign | lateral truck, hanging box as foreground parallax, the frame rising and falling with the jumps | strike in sequence, caused by the landings; chaser as a conveyor |
| 5 | 15.5–25.0 | Turns, peers over the bowl, a paw in twice (the fish darts away), a wiggle; pounce at 18.5: a white flash at the paw, a 7 cm gap in the bowl tube, four glass chips falling; the bowl goes pale violet and flickers; the three water lines go out one level at a time (19.0, 20.0, 21.0), the fish flops on the dry bottom, darker every beat; the bowl dies a section at a time toward its electrodes, the 金魚 sign fails (22.0); ears back (22.0), half a step back (22.5), a look down (23.0), one silent beat (23.5); dives in and comes up with the fish (24.0–24.5) | locked medium, slow push on the cat from 22.0 | crack and drain; the film's only silent beat |
| 6 | 25.0–33.0 | Chorus. Drops to the street; runs left along the base of the wall, the fading fish in its mouth, its upside-down twin in the puddles; a leap over the alley mouth mirrored in the water; a wide where a chase wave follows it along the street, the microphone and window frames swap circuits and the arrow chases left; back at the water a drop breaks its reflection (31.0); three jumps up the café facade to the goblet | follow tilt down → puddle-level truck (eye 0.3 m) → hard cut to the wide (28.5) → puddle level → rise with the climb | puddle-level chase; chorus chasers; rise from the reflection |
| 7 | 33.0–37.5 | The cat on the goblet's rim opens its jaws; a crown of small white tubes at the waterline; the fish sinks and goes out; one silent beat; at 34.0 the fish strikes back to full red-orange and swims round the ice; the cat closes its eyes | locked medium | strike = life; 冰室 ICE CAFE readable 4.5 s |
| 8 | 37.5–44.0 | Pull back and rise to half the street: the clock rolls to 2:00, the rain stops, signs go off one per beat toward the café, shutters come down; only the goblet, the fish, the cat and 冰 stay lit; push in: the cat curls up, its eye goes out (41.5); fast tilt into a puddle (42.4–42.95), the last drip breaks the reflection (43.3) | pull back and rise → push in → fast tilt down | one sign left, doubled in a still puddle |
| 9 | 44.0–48.0 | End card on the café's roller shutter; at 46.5 the sleeping cat's eye strikes open and glances at the fish, which darts behind an ice cube | static | — |
Score structure
Electronic city pop in F major, 120 BPM, bar lines on even seconds; everything synthesised (audio.py).
| Section | Time | Palette | Notes |
|---|---|---|---|
| Wake | 0–4 | transformer hum, the cat's purr (hum with a 25 Hz tremor), filtered pad; kick from 2.0 | the eye's strike crackles; a bell when the light reaches the tail |
| Fish | 4–8 | bell motif A–C–D–C–A–G–F, 8th hats, bass pedal | the motif comes back softly at 16.0 |
| Verse | 8–15.5 | four-on-the-floor, claps on 2 and 4, 16th hats, syncopated bass, FM electric piano; B♭–C–Am–Dm | every sign that strikes plays the next note of a rising F pentatonic pluck line; ticks and a sweep while the clock spins |
| Pre | 15.5–18.5 | kick on the one, 8th hats, held bass on Gm | relay clicks on every pose |
| Break | 18.5–23.5 | drums and bass out; pad Dm → B♭ → Gm, closing down | glass ting and sizzle on the crack, three gurgles as the water drains, slaps as the fish flops |
| Silence | 23.5–24.0 | hum and rain only | |
| Build | 24.0–26.0 | splash, snare roll rising to the downbeat | |
| Chorus | 26.0–33.0 | full kit, open hats, crash, lead hook with a ping-pong echo; B♭–C–Am–Dm | music +2 dB; wet footsteps |
| Splash | 33.25–34.0 | music stops | splash, glass ting |
| Revival | 34.0–37.5 | F add9 chord on the strike, half-time groove, the hook once more, softly | |
| Closing | 37.5–44.0 | pad B♭ → F; a falling bell for each sign that goes off | drips, the last drop's plop |
| End card | 44.0–48.0 | F major 9 rings under the card | a pluck and a bubble on the eye striking open |
Mix: the music sits under the foley and ducks by the foley's level; 3rd-order high-pass at 48 Hz; the pre-master is −16 LUFS with true peak −5.5 dBTP so that mux.sh lands at −14.0 LUFS, true peak −1.7 dB. All cue times come from events.json.
Palette & props
- Cat: phosphor-coated turquoise outline, pink eye (almond, slit, wide or closed), whiskers and tail as thin tubes; sitting height about 0.95 m. Goldfish: clear tube with neon, red-orange, about 0.35 m.
- 金魚 GOLDFISH: navy board #0a1626; a white phosphor fishbowl (R 0.5 m) breaking the board's top edge; three argon-blue water lines; white bubbles, yellow pebbles, green weed; 金魚 in yellow phosphor, GOLDFISH in argon blue; aquarium tanks glowing in the shop window.
- 冰室 ICE CAFE: oxblood board #2a0b0d; an argon-blue goblet drawn with the same wavy water line as the fishbowl, two white ice cubes, a pink straw; 冰室 in neon, ICE CAFE in argon blue; a neon clock with an argon ring.
- 旅館 HOTEL: a black box hanging 2 m in front of the wall (yellow 旅館, pink HOTEL) and a neon arrow over the door with a head at each end. 歌廳 KARAOKE: aubergine board, a microphone in two circuits (pink / argon), window frames in pink and turquoise. 藥房 PHARMACY: green crosses, white hanzi. A dark alley between the karaoke building and the goldfish shop.
- Facades: plaster, mosaic tile and brick; shopfronts with warm, cool and violet interiors; roller shutters after closing; AC units, drainpipes, cables.
End card
The ice café's roller shutter, lit from above by the goblet: 夜宵 (Noto Sans SC 900), MIDNIGHT SNACK, 霓虹燈管 NEON TUBES, LemoLab × Claude Opus 5.5 (Barlow Condensed Bold, about 32 px), stencilled in the lower left of the shutter, away from the sign. 4.0 s, static; the eye-open gag plays on the sign above, never over the lines. 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
demo/
build.sh one command: fonts (if missing) → glyphs.json → art.json → events → mix → picture → master → readcheck → poster, styleframe
index.html one canvas; loads film.js
film.js render(t): timeline T, circuits (strike, chasers, the cracked bowl), character keys (K_, jump, run), fish keys,
cameras per shot, drawing (tubes, facade, clock, rain), uniforms for gl.js, TEXTS, EV
world.js gas colours, the street, signs, fishbowl and goblet placement, artTube
lib.js polylines, fillets, tubeFromStrokes (caps per end), hanzi / latin from glyphs.json
gl.js WebGL2: glass shading, surface lighting from the emission pyramid, wet street, puddles, ripples, post
glyphs.json neon hanzi and Latin capitals (tube centrelines)
art.json 39 cat poses, 9 fish frames, the fishbowl and the goblet (generated)
audio.py score + foley from events.json -> mix.wav
tools/glyphs_build.py the neon hanzi, laid on Noto Sans SC's skeleton -> glyphs.json
tools/glyph_check.py overlay of every neon hanzi on the font, to check stroke positions
tools/art.py the pose rig and every pose (add a png path to get a sheet of all poses) -> art.json
tools/sdf.py signed-distance and polyline helpers for art.py
tools/fonts.py Noto Sans SC subset for the end card
FACTS.md the medium's facts, sources, quoted wording
sh demo/build.sh(renders at 30 fps with--workers 2;WORKERS=3for more). Needs only the core tier: no voice model, no sample libraries. On the first run it downloads Barlow Condensed Bold and the Noto Sans SC variable font from github.com/google/fonts intodemo/fonts/(gitignored). Deletedemo/fonts/NotoSansSC-sub.ttfafter changing the end card's text.- 1080p: about 40 ms a frame on Apple silicon; the whole film renders in about 25 s with 3 workers.
render(t)depends ontonly: rain, ripples, flicker, poses and the crack are closed-form. - Needs WebGL2 with
EXT_color_buffer_float(falls back to 8-bit targets: flatter highlights). - Readcheck (
node core/render/readcheck.mjs styles/neon-tubes/demo) passes: 金魚 / GOLDFISH 2.60 s (needs 2.03 s), 冰室 / ICE CAFE 4.48 s, the end card's four lines 3.96 s (the longest needs 2.99 s). The other signs are scenery and are not reported. - Demo-specific pitfalls: in a macro the eye height must equal the subject's height, or the 5 cm stand-off of the tubes throws the subject out of frame; the match cut computes the eye's camera from the bowl's screen position and radius; a puddle-level reflection needs the mirrored object within two screen heights above the frame (the final tilt uses K = 280 for that); the cat's afterglow is limited to jumps, because on a run every frame's ghost reads as a second cat.