RelayCTX Creative marketingexplainerREADME.md
RelayCTX Creative · Document

Explainer films

1,797 words · 8 min View raw Source History

Explainer films

Six paper-collage explainer films and six feature shorts for Relay, playable in the browser with voice, score and foley. Each has a full cut and a 15 s cutdown, and each plays in 16:9 and in 9:16 (vertical, with burned-in captions). Draft for EC review. Stealth: not for public channels. All external copy goes through Ada (relay-gtm) before it ships.

Running a campaign with this kit? Start at relay-marketing video/PLAYBOOK.md (what exists, one-time setup, making a post, a short or a lesson, the gates). Then plan the campaign in relay-marketing briefs/. This folder is where the pieces are made. Any session can load the kit by claiming the Relay series relay-campaign-kit.

FilmFolderVoiceFull15 s
A · Blank Pageblank-page/Kokoro af_heart0:380:15
A2 · Blank Page · Together (sharing, collaboration)blank-page-together/Kokoro af_heart0:340:14
B · Mid-Thoughtmid-thought/Kokoro bf_emma0:420:14
C · The Batonthe-baton/Kokoro bm_george0:430:14
D · Pass It On (the baton, cute, with the paper runners)pass-it-on/Kokoro af_heart0:370:15
E · Fridge Door (Relay at home)fridge-door/Kokoro af_heart0:340:15
F · Connecting the Dots (the campaign film: the week drawn into a paper plane)connecting-the-dots/Kokoro af_heart0:18(is short)

Feature shorts (shorts/<feature>/, about 15 s, 16:9 and 9:16): Streams, Series, Sessions, Recall, Forward, Look first, Expiry, Team, Status, Search. Each is one feature: the problem, the feature, the payoff. They share engine/shortkit.js (timing laid out from the voice, the feature label, the end card, a score), so a new short is only its own scene. Draw only what the docs state about a feature. Idea shorts (shorts/idea-*/) say the deck's positioning plainly, one move each: The invisible wall, Not another tool, Any tool you like, If it speaks MCP, You own what travels. The concept is /concepts/big-ideas. Side-by-side shorts put Relay next to a tool a viewer already knows, for one viewer at a time: beads + Relay (shorts/beads-and-relay/, 0:28 and a 0:18 cut) has six voice lines, so it lays out its own timeline and end card instead of shortkit's four-line one. Life shorts use the same kit for the core loop at home: The sitter (shorts/dog-sitter/), The trip (shorts/group-trip/), The recipe (shorts/recipe/), Moving day (shorts/moving-day/), Study group (shorts/study-group/), The gift list (shorts/gift-list/), The leak (shorts/the-leak/) and Road trip (shorts/road-trip/). Lesson shorts (shorts/lesson-<n>-<slug>/) are the onboarding series First Relay, in paper (relay-marketing briefs/onboarding-paper-series.md): one onboarding step each, opened by a Lesson n of 6 tab and closed on Next: …. lessonOf(n, name, next) in shorts/_kit.js gives any short that accepts it (a third argument to its film) the lesson's label, tab and close; lessonCut makes a lesson from a longer film's segments. Lessons 1 and 3 (shorts/lesson-1-wrap-it-up/, shorts/lesson-3-another-tool/) are new drawing; 2 is the Boots from a Code scene with its own lines, 4 is Streams as it is, and 5 is cut from Together. 4 and 5 read their voice from the source folder (base in their index.html), so there is one copy of it. Line shorts (shorts/line-<n>-<slug>/) are Line by line, the journey building Relay, one chapter per short (relay-marketing briefs/how-relay-came-to-be.md, concept first-line/): first person, the short kit's four beats as the wall → what got built → how → the receipt. shorts/_lines.js holds what they share: the Line n · building Relay tab, the paper receipt (receipt(ctx, tq, t0, rows), never dated before 2026-04-17), the journey map (lineMap) and the Line by line. close; lineOf(n, name) wires them in the way lessonOf does. Line 4, Ran out of room (shorts/line-4-ran-out-of-room/), is the first. Concept shorts cut a concept as a short: Boots from a Code (shorts/boots-from-a-code/), scenes 1 and 2 of second-brain/. shorts/_kit.js holds the scene pieces the later shorts share: the paper phone, the Code message, the wrap-up into a Code, a hand lens.

The character kit (crew/svg.html, files in svg/, Figma plugin in figma/): the character as SVG components. engine/svg.js records the engine's drawing as vectors:

Re-export after any change to the cast with BASE=http://127.0.0.1:8124/marketing/explainer node marketing/explainer/tools/svgkit.mjs. The Figma plugin (import figma/manifest.json in Figma desktop) builds colour styles, a component set per part, a composable Character with swappable parts, and a concept board.

The cast (engine/crew.js, sheet at crew/): Page, the original, and seven characters dressed for the work people do: Memo (office), Plumb (trades), Pitch (sales), Doodle (creative), Chalk (teaching), Crumb (hospitality), Sticky (home). crew(ctx, id, x, y, opts) takes any buddy option; bare: true draws the paper without the outfit. No black or dark paper, no skin-like tones (EC, 2026-09-25): tools are told apart by sky, mint, lilac, butter, graph, ruled and dot grid.

Asset Builder (builder/): post images from the same engine and cast in six formats and five layouts. Copy presets come from brand/messaging.json, which is lifted from canon (the voice guide and the social-accounts guide); the never-list is flagged as you type. A design is a URL. Copy pack entry gives a line for a pack file, and tools/pack.mjs renders a whole pack (marketing/packs/<pack>/pack.json, with each post's caption) to PNGs beside it.

Gallery: marketing/gallery/ shows every film, short, the cast and the packs, with posters.

index.html is the review page: a player with film, cut and format switches, the comparison, the timed scripts and the decisions before a final cut. Each film also plays alone at <film>/index.html. Add ?cut=15 for the cutdown and ?format=vertical for 9:16.

Marketing catalog: relay-marketing video/ holds one entry per film: its job, segments, gates, use-in-outreach notes, alt text, the timed scripts and SRT captions. The scripts and captions there are generated from this folder by tools/catalog.mjs, so this folder stays the source. After changing a script, regenerate the voice and re-run the catalog.

How it's built

Everything is JavaScript. There is no video file in the repo and no editing software involved.

Rebuild

Serve the repo root (the pages resolve the token stylesheet by relative path):

bash
npx http-server -p 8124 -c-1 .          # from the relay-creative root
TaskCommand (from a working dir with npm i playwright)
Regenerate voicepython3 marketing/explainer/tools/vo.py marketing/explainer/<film>/script.json [line ids]
Rebuild the sample banknode tools/bank.mjs <explainer dir> blank-page mid-thought the-baton (needs SF= pointing at FluidR3 per-note MP3s)
Stillsnode tools/shot.mjs <film> 3.5 10.8 → out/<film>-<t>.png
1080p MP4node tools/render.mjs <film> → out/<film>.mp4 (24 fps, x264 CRF 18, AAC 192k). Env Q="cut=15&format=vertical" (or --q) for other cuts and formats: the output is named from the query (out/<film>-15-vertical.mp4) unless TAG/--tag names it. Honoured since paper-studio 1.2.2
Campaign renderQ="invite=BLANKPAGE&x=blankpage&cut=15" TAG=-blankpage node tools/render.mjs blank-page
Marketing catalognode marketing/explainer/tools/catalog.mjs <relay-marketing>/video
A post packnode marketing/explainer/tools/pack.mjs marketing/packs/<pack>/pack.json (writes the PNGs beside it)
Loudness by stemnode tools/stems.mjs <film> && python3 tools/loud.py <film>

The voice uses Kokoro v1.0 (82M, Apache-2.0), run locally from /opt/tts/kokoro-v1.0.onnx and voices-v1.0.bin (the thewh1teagle/kokoro-onnx releases), with pip install kokoro-onnx soundfile scipy imageio-ffmpeg. Codes are spelled with an explicit phoneme override (code_ph in script.json), so "A9M4FG" is read letter by letter. The brief asked for OpenRouter TTS, but the session's network policy blocked openrouter.ai. Any line can be swapped for a hosted or human read by dropping an MP3 of the same id into <film>/vo/ and updating its dur in vo.json.

Rules these films keep

Credits

Instrument samples: FluidR3 GM, rendered to per-note MP3 by gleitz/midi-js-soundfonts (MIT). Fonts: Cormorant Garamond, Outfit, JetBrains Mono and Caveat (SIL OFL 1.1). Voice: Kokoro v1.0 (Apache-2.0).