Video lab
Test-generate a Wallace video in TimDS’s local Video Lab: draft or load an answer, edit the beats, inspect the plan, render, and review the MP4 and cover in your browser. The lab uses this repository’s contract, registered media, and authored components in video/remotion.tsx. Remotion renders the frames headlessly; the lab itself is a separate web app.
Open the lab
Run npm run timds -- check to build the writing-brief index, then npm run video:lab. Open the local Video Lab and keep its server running. The video-lab launch configuration runs the same app from either the website or standalone Design System checkout.
- Load a saved input, paste a compile request, or describe a source for Draft. Draft uses the Anthropic credentials available to the server; the rest of the app works without them.
- Edit the exact question, topic, format, and answer beats. Check the plan to review scene timing, copy, footage chains, and cover selection.
- Save a deliberate fixture under
video/lab/, then render. Review the MP4 and thumbnail in the app; they remain under ignoredvideo-local/lab/<name>/out/.
| Command | Does |
|---|---|
npm run video:lab | Starts TimDS’s web app on 127.0.0.1:4410 |
npm run video:lab -- --port 4500 | Uses another local port |
npm run timds -- video lab <name> --plan | Prints scene timing, copy, footage chains, and cover without downloading media |
npm run timds -- video lab <name> --prepare | Stages media and writes the generated entry without launching |
npm run timds -- video lab <name> --render | Renders the video and cover headlessly |
npm run video:studio -- <slug> | Opens the separate Remotion Studio inspector for a ready production |
npm run timds -- video lab --list | Lists inputs and ready productions |
Drafting reads the exact-version dist/design-system/index.json. Rebuild with timds check after pulling a release or editing a writing-brief page. Credentials come from ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, or an ant auth login profile; keep them out of launch files.
What the lab renders
Everything runs at 30fps. A lab input renders one format, the way the automated Video Lab ships one production per format; a ready five-record production renders the whole long-form-plus-short family.
From a lab input
| Composition | Output | Size | Component chain |
|---|---|---|---|
TimDSVideo | The video, in the input’s outputFormat | 1920 × 1080 horizontal · 1080 × 1920 short | Video → Scene → Media, CaptionPages, BrandWatermark; Intro and Outro on their cards |
TimDSCover | The cover still for that format | 3840 × 2160 horizontal · 1080 × 1920 short | HorizontalCover or VerticalCover → CoverVisual, GoldHeadline |
From a ready production
Listed by the production slug in PascalCase; shorts are numbered in the order the production declares them.
| Composition | Output | Size | Component chain |
|---|---|---|---|
<Slug>Long | Long-form video | 1920 × 1080 | Video → Scene → Media, CaptionPages, BrandWatermark; Intro and Outro on their cards |
<Slug>Cover | Long-form cover still | 3840 × 2160 | HorizontalCover → CoverVisual, GoldHeadline |
<Slug>Short1 | Vertical short | 1080 × 1920 | The same Video and Scene components with vertical set |
<Slug>Short1Cover | Short cover (frame zero) | 1080 × 1920 | VerticalCover → CoverVisual, GoldHeadline |
Two kinds of footage, one Media component
A content scene declares one registered asset or an ordered chain in assets. Each entry plays at natural speed for its share of the scene under the same slow push-in; the kind of asset decides how it is drawn.
| Workflow | Asset kind | Drawn as | Screen time |
|---|---|---|---|
| Crash Cam | video — a dashcam or security-camera clip | Muted video at 1× speed, cut at the scene boundary | Its measured duration, never stretched |
| Character Story | image — a character still | A held still with the same push-in, so it never reads as a freeze | The rest of the scene, or its share of a chain |
video/footage.ts re-exports TimDS’s rules for the components and CI: consecutive picks must come from different footage families (offset, mirrored, and vertical derivatives are the same family; intro and outro cards break the sequence), a chain must cover the scene at natural speed, and the last clip holds at least two seconds by cutting the previous clip early. A scene that breaks a rule fails rendering and fails npm run check:video.The component contract
The engine receives one map, wallaceVideoProjectComponents, exported at the end of video/remotion.tsx. Every entry starts as the TimDS default that was copied into the file; replace an entry to change that surface, and the engine keeps the rest. Props types are imported from @dtconcepts/timds/video/remotion, so a replacement is checked against the same contract the engine calls.
| Entry | Props | Owns |
|---|---|---|
Video | project, scenes, ids, pads, audioSrc, vertical | Sequences the scenes from the measured caption timings and plays each line’s voice take. |
Scene | project, scene, line, duration, lead, vertical | One content scene: footage, the eyebrow/headline/subline panel, watermark, and caption lane. |
Intro | project, question, vertical | The footage-free question card that opens a production. |
Outro | project, vertical | The footage-free brand card: logo, site, tagline. |
Cover | project, cover, vertical | Both cover stills unless a format-specific entry is set. |
HorizontalCover | project, cover | The 16:9 cover, composed on a 1280 × 720 grid and scaled to the export size. |
VerticalCover | project, cover, vertical | The 9:16 cover that becomes frame zero of every short. |
Media, CaptionPages, BrandWatermark, CoverVisual, and GoldHeadline are exported for reuse inside a replacement but are not override points; a new Scene composes them rather than the engine.Rules for a Wallace component
The same discipline as a marketing component, applied to a frame: consume the contract, never restate it.
- Brand comes from the contract. Colours, panel, fonts, logo, series, site, tagline, and watermark labels are read from
project.contract.brand, which mirrors Brand. A literal colour or a second font family in a component is a defect; when the contract and Brand disagree, Brand wins and the contract is fixed. - Copy is data, not layout. Eyebrow, headline, gold phrase, subline, and caption words arrive on the scene and caption records already validated against the word budgets (8 headline words horizontally, 8 in a short, 5 words per caption page). A component draws them; it never truncates, rewrites, or invents them. Wrap headlines with
tieOrphanso no line ends on a single word, and highlight exactly one gold phrase. - Footage plays at natural speed. Never slow, hold, loop, or freeze a clip to fill a scene. A chain that is too short is a production defect the render must surface, not a visual one to hide.
- Every frame carries brand and contact copy. Content scenes show the logo top-left. Horizontal frames keep both bottom labels and the Subscribe for more banner top-right. Vertical frames show Contact Wallace Pierce and wallacepierce.com under the logo, with the left watermark alone at the bottom. Intro and outro retain the banners. The vertical action rail stays clear.
- Text sits opposite the subject. Read the asset’s
textandsubjectplacement rather than centring copy over a face or an impact. The vertical scrim under full-bleed footage stays; 16:9 panels carry their own fill. - Never draw a logo. The mark is always
Imgofbrand.logo. A component that recreates, recolours, or reproportions it fails review. - A frame is a pure function of the project and the frame number. No dates, randomness, network, or machine paths. The same records must render the same pixels on every machine and in CI.
- Stay inside the map. Edit
video/remotion.tsxandvideo/footage.tsonly. Do not add a second engine, a per-topic TSX file, a render script, or edits under ignoredvideo-local/; do not runtimds video components initagain —--forcediscards every Wallace change and is only for an explicitly requested reset.
Gates
What runs on every change, locally and in CI. A rule that is not on this list is guidance, not a gate.
| Command | Checks |
|---|---|
npm run check:video | TimDS validates the contract, the producer block, the asset catalog, and every ready production; the footage-chain and headline-copy gates run over video/productions/; the component, footage, producer, strict fixture-finalization, and live lab-server tests run; video/remotion.tsx typechecks against the engine’s types. |
npm run check:versions | React and Remotion resolve to the single hoisted copy the engine uses. Two copies break React context at render time. |
npm run check:media | Every asset a production can reference is published through TimDS. |
npm run timds -- check | Builds the viewer and machine index. |
npm run check:video-lab | After the build, resolves the producer’s writing-brief blocks for both formats against the exact-version index; CI runs this without calling a model. |
node --import tsx scripts/check-video-footage-chains.mjs video/drafts and node scripts/check-video-copy.mjs video/drafts.Automated Video Lab
An outside lab compiles a reviewed answer into a Wallace production without knowing Wallace: the producer block in video/contract.json owns the role labels, the intro/engagement/outro structure, the CTA wording, and the asset-key vocabulary, and TimDS supplies the compiler and deterministic footage selection. The writing brief is assembled from the published Design System blocks the contract cites, so voice direction lives on these pages and nowhere in lab code. The local app uses this same compiler and client component module for its headless renders. When a local media file is missing or empty, TimDS downloads the published asset from the Design System cloud through media.json; a fresh workstation needs no copied media cache.
| Beat role | Eyebrow |
|---|---|
hook | What happened |
rule | North Carolina law |
risk | What can go wrong |
process | What to do |
exception | The exception |
answer | The takeaway |
engage | What would you do? — a yes/no question the viewer can answer, horizontal only |
outro | The fixed brand card |
Engagement narration {{question}} Tell us what you would do in the comments. Long-form outro If this happened to you, contact Wallace Pierce at {{site}}. Subscribe for more about {{topic}}. Short outro Contact Wallace Pierce at {{site}}. Cover eyebrow Dashcam · North Carolina Footage keys dash-*, cc-*, char-broll-*, character-broll-*, environment-broll-*, object-broll-* in video/assets.json Cover keys cover-subject-* in video/assets.json Brief blocks brand/voice#four-rules brand/voice#words video/workflow#the-two-types video/workflow#production-rules video/b-roll#forbidden-in-every-clip video/b-roll#automated-selection
What the producer can ship today. Automated horizontal and Short videos can select from the complete published B-roll catalog, including dashcam, security-camera, character, environment, and object clips. TimDS matches the configured prefixes directly to the original asset keys. Every lab input is compiled and finalized in npm run check:video, and the producer and authoring tests check complete catalog coverage in both formats. The cover library the producer chooses from, cover-subject-, holds neutral scene stills, because a Crash Cam cover is a dashcam frame or a neutral scene and the producer selects images only; Character Story covers still resolve through Thumbnails by hand. Automated Shorts use published derivatives linked through each master’s vertical field; the live-crop fallback stays disabled. The crash-footage-short fixture keeps this render path checked alongside horizontal video. Changing a component
- Branch
design-system/<change>. Editvideo/remotion.tsx; keep caption paging invideo/footage.ts, shared footage rules in TimDS, and a component test invideo/remotion.test.ts. - Render both horizontal and short fixtures in the lab and inspect the first, middle, and last frame of every scene, then the cover. Check headline fit, caption lane, watermark, and subject collisions.
npm run check:video, thennpm run check,npm run timds -- check, andnpm run check:video-lab.- Record the change under
## UnreleasedinCHANGELOG.md, update this page if a rule or gate changed, and submit withnpm run timds -- submit. - To adopt a newer TimDS default, diff
node_modules/@dtconcepts/timds/video/remotion.tsxagainst the Wallace file and port the change by hand. The generator never overwrites it.
Owner: Wallace Pierce Design System