Skip to content
§ 07c · Production plan · Graphics

The graphics package

Every on-air graphic for Bromont — what it is, which engine builds it, when it fires, and the build order.

Three engines split the work. After Effects (on the Mac Mini, pre/post-show only) masters the pre-rendered cinematic moments — its MP4 outputs play back as media during the live broadcast. SPX-GC (on the VPS, consumed by the iMac as a browser source) handles the data-driven scoreboards and lower thirds. NewBlue Captivate runs open on the iMac during the stream as a live co-piloted redundancy — primary path is AE + SPX-GC, Captivate sits ready for the moments where it's faster to fire or where the primary engines fall over. This doc maps every graphic to its engine and gives the order it gets built in.

MARS Bromont CCI 2026 — Graphics Build Plan

Show: MARS Bromont CCI 2026 (CCI4*-L/S, CCI3*-L + U25, CCI2*-L + U25, Bromont Rising) Day 1: 2026-06-04 (T-19 days from 2026-05-16) Owner: Mike Schiffman / Real Neat Solutions Distribution: YouTube Live, Bromont brand only (no CMH/H&C lockups, no broadcaster compliance) Brand source: brand-packs/bromont.json + Bromont/bromont-brand-book/ (https://bromont.schifftacular.com/)


Architecture (locked)

LayerEngineWhere it runsRole
Pre-rendered motion (intros, bumpers, stings, EOD, story package)After Effects (rendered to ProRes/PNG-seq, played from OBS Media Source)Mac Mini at Hickory Hills, pre/post-show only — does NOT run during the live streamPrimary
Live rundown layer (lower-thirds, scorebug, leaderboard, fence callouts)SPX-GC (browser source)VPS in the cloud; iMac consumes as a browser source over the public internetPrimary
Live redundancyNewBlue CaptivateiMac at Hickory Hills, open and running for every minute of the broadcast alongside OBSCo-running redundancy (not cold). Mike triggers from Captivate when AE/SPX falls over OR when Captivate is faster to fire. Refines 2026-04-29 split-engine memo per [[project_bromont_build_decisions]] + [[project_bromont_architecture_corrections]].
Atomic chassis swap (primary slot)SPX-GCVPSOperator-fired from console menu

Build rule: Anything that needs to swap atomically on primary-slot change or fire from the operator menu mid-rider lives in SPX-GC. Anything cinematic, stinger-like, or longer than ~5s of motion lives in AE.

Captivate fallback rule: A graphic only earns a Captivate twin if its absence would break the show's information contract with the viewer (rider name, score, country, leaderboard, sponsor bug). Cinematic motion is not mirrored — if AE dies, we live without bumpers, not without lower-thirds.

No TPS for Bromont ([[project_bromont_no_tps]]). Every "data-bound" graphic below sources from Postgres on the VPS, populated by operator action or manual scorer entry — not from a venue timing feed. No auto-fire on TPS events anywhere.


Phase 0 — Pre-Show / Cross-Phase

Tier 0 floor

GraphicEngineAsset listData bindingTriggerCaptivate fallbackEffortDependencies
Corner bugAE (looped PNG-seq) + SPX-GC (static fallback)bug.svg from brand pack, MARS-Bromont indigo bug 52pxStatic asset referenceAlways-on (OBS source toggled per scene)Yes — static PNG on OBS sceneSBrand pack ratified
Lower-third banner (rider name / country / horse)SPX-GCRider roster JSON, country flag setshows/bromont-2026-06/data/riders.json → SPX rundown rowOperator menu (per-rider)Yes — full Captivate twin, identical fields, indigo chassisMRoster import
Lower-third banner (score / penalties)SPX-GCScore schema per phasePostgres scores table (manual entry by scorer or scraped from OC's published results)Operator menuYes — Captivate twin with manual data entryMScore data pipeline, phase schema
Leaderboard (sortable per phase)SPX-GCFull division roster, current standingsPostgres view per division/phaseOperator menu (toggle on/off, scroll)Yes — Captivate static top-10 page per division/phase, refreshed manuallyLPostgres scores schema, sort logic, EN/FR labels

Commentator dossier / teleprompter surface is tracked as its own non-broadcast workstream — see the dossier project plan, not this document.

Tier 1 cross-phase

GraphicEngineAsset listData bindingTriggerCaptivate fallbackEffortDependencies
Division indicator (CCI4-L/S, CCI3-L + U25, CCI2*-L + U25, Bromont Rising)**SPX-GCDivision ID strings, level color treatment from brand packDivision flag in show configOperator menu (set at top of each division block)Yes — Captivate static division ID cardSDivision roster keyed in show config
EOD wrap templateAE pre-renderFinal standings top-10 + Sunday tease stillPostgres final standings export → AE data merge (one render per division per day)Operator end-of-day cueNo — AE-only acceptableMEOD render workflow
Story package template (rider feature, 30-60s)AE pre-renderRider portrait, B-roll, captions, music bedHand-edited per packageOperator menuNo — AE-onlyLStory selection + B-roll capture by Hank's cam crew
Replay bumper (in/out stinger)AE pre-render1–2s stinger eachStatic, no dataOperator menu (paired with OBS replay scene)No — AE-only; without it, replay just cuts cleanlySBrand motion ratified

Phase 1 — Dressage

Dressage rail color: mauve #7B5BAA (phase token). Intro-card rail uses this tint; type stays indigo. Live scoring graphics fall back to the cross-phase lower-third (score / penalties).

GraphicEngineAsset listData bindingTriggerCaptivate fallbackEffortDependencies
Per-rider intro card (bio / horse / country / last result / story-link)AE pre-render (one per starter, batch-rendered ~1 hr before phase block)Rider portrait, horse photo, flag, last-result stringriders.json + dossiers.json → AE data merge via brand pack tokensOperator menu — fires from on-deck listYes — Captivate "intro card lite": name + country + horse only, no portraitLRoster + portraits + dossier text

Name-order rule (locked): Intro cards render FIRST name in big UPPERCASE on top, LAST name title-case smaller below (see [[feedback_rider_card_name_order]]). Opposite of football convention. Inter 700–800.


Phase 2 — Show Jumping

SJ rail color: arena turf #3E8B5C.

GraphicEngineAsset listData bindingTriggerCaptivate fallbackEffortDependencies
SJ Timer scorebug (Bromont-skinned)Browser-source HTML app (sj-timer.schifftacular.com, already prototyped)Bromont brand tokens, course config (jumps, time allowed)Local timer state + Postgres score syncOperator (sj-timer UI)Yes — Captivate static fault/time card, manually updatedMTimer app re-skin to Bromont brand, course config import
SJ per-rider intro cardReuse Phase-1 AE card (same template, SJ phase tint)Same as D introSameOperator menuYes — same Captivate lite cardSPhase-1 card built
Fault / refusal indicatorSPX-GCPenalty schemaTimer app + manual operator confirmAuto on eventYes — Captivate twinSSJ Timer integration
SJ final standings (per division, end-of-phase)SPX-GC (leaderboard view filtered to SJ)StandingsPostgresOperatorYes — Captivate static top-10SLeaderboard built

Phase 3 — Cross-Country (highest density)

XC rail color: saddle leather #A4733A.

XC menu-fired graphics

All XC content fires from the operator console menu (locked design pattern). Templates must accept a primary-slot ID and render atomically on swap.

GraphicEngineAsset listData bindingTriggerCaptivate fallbackEffortDependencies
XC opener (live wide + pre-recorded fence broll cut-ins)AE pre-render (B-roll edit) + OBS scene composite (live wide)Fence broll captured pre-show, music bed, anniversary title cardNone (cinematic)Operator (top of XC block)No — AE-onlyLFence broll capture day, 50th-anniversary lockup design
Per-rider stopwatch (running clock on-air)SPX-GCInter tabular numerics, indigo chassisLocal timer state, atomic swap on primary-slot changeManual operator press when rider leaves the start box (console button / shuttle). No TPS auto-start.Yes — Captivate twin (loses atomic-swap fidelity; manual cut acceptable in fallback mode)MPrimary-slot mechanic implemented in console

XC layout templates (4 total)

These are OBS scene compositions authored to take the SPX-GC overlay + camera buses as inputs. They're not graphics in the strict sense — they're the chassis the graphics live in. Listed here because they gate the visual product.

LayoutDescriptionEngineEffort
HEROSingle full-frame cam + chassisOBS sceneS
START BOX PiPHero + start-box insetOBS sceneS
REPLAY + LIVEReplay full + live PiPOBS sceneM
LEADERBOARD + INSETLeaderboard full + live cam insetOBS scene + SPX leaderboardM

Built via orchestrator/scripts/obs_scene_builder.py from shows/bromont-2026-06/obs/scene_config.yaml. Don't hand-edit in OBS.

Tier 2 (stretch — only if Tier-1 is complete by 2026-05-30)

GraphicEngineEffortRisk
Course-map graphic with live position dotsBrowser source (SVG + operator-driven or CV-driven position state)LHigh — Bromont has no TPS feed, so position data comes from either manual operator scrubbing of the rider's last known fence (from POC chatter) or Claude CV detection on the Mac Mini (not built). Likely slips.
Sponsor fire-count trackerBrowser source (counts bumper plays per sponsor across show)MLow — data-only; cosmetic

Asset Gathering Checklist

Nothing below is optional. Anything missing on 2026-05-30 is a build blocker — escalate immediately.

Rider / horse data

  • Final rider roster per division (CCI4*-L, CCI4*-S, CCI3*-L, U25 CCI3*-L, CCI2*-L, U25 CCI2*-L, Bromont Rising) — CSV or JSON, FEI ID where possible
  • Horse data per pair (name, breed, age, owner, sire/dam if available)
  • Rider portraits (min 1200px square, headshot framing) — gap-fill with generic silhouette card
  • Country / flag mapping (ISO 3166-1 alpha-3, render via standard flag set)
  • Last-result string per rider (for intro card "FROM: <previous show> <result>")
  • Story-link / dossier text per rider (1-2 sentence pre-written for commentator)
  • Hometown strings in the bromonthorsetrials.com press-release style ("Dunham, Quebec's Colleen Loach")

Course / venue

  • Final XC fence list with numbers + names + GPS coordinates (gates Tier-2 course map)
  • XC fence broll capture day scheduled before 2026-06-03 — fixed plates for XC opener cut-ins
  • SJ course config per division (jump count, time allowed, distance) for SJ Timer
  • Venue wide shot / drone plate for XC opener

Sponsor logos

  • Title sponsor — MARS Bromont lockup SVG (already in brand pack at assets/brand/bromont/MARS-Bromont-LOGO-2020-TALL_SIGNAGE_RGB.svg) — drives the persistent corner bug
  • 50th-anniversary lockup — currently a placeholder in brand pack. Needs design or confirmation that anniversary stays off-broadcast.

Sponsor inventory beyond the title sponsor + anniversary lockup is out of scope for this graphics package — corner rotation, sponsor lower-third, and marquee fence bumpers were all dropped. If any sponsor placement comes back into scope (EOD wrap acknowledgments, etc.), reopen this section and pull tier-partner + official-partner logos at that point.

Brand pack ratification

  • brand-packs/bromont.json accepted as-is (no edits expected — palette/type are HIGH confidence). Confirm anniversary gold #C8A557 is contractually correct or drop from broadcast.
  • EN/FR bilingual strings pre-typeset for every persistent label (lower-third, leaderboard headers, division IDs)
  • Fraunces + Inter + Recursive Mono fonts licensed and installed on AE rig and SPX-GC server

Pipeline / infra

  • shows/bromont-2026-06/data/ populated with roster + dossier + scores schema
  • Postgres scores table provisioned with phase + format columns
  • OBS scene_config.yaml written and applied via obs_scene_builder.py
  • Operator console menu wired to SPX-GC rundown + AE media triggers
  • Replay rig OBS scene built (paired with replay bumper)

Captivate Fallback Roster (minimum redundancy set)

These graphics must exist in Captivate as well as their primary engine. If the AE/SPX rig fails on show-day, the show can continue on Captivate alone with degraded but coherent graphics.

GraphicWhy mirrored
Corner bugIdentity contract
Lower-third (name / country / horse)Information contract
Lower-third (score / penalties)Information contract
Leaderboard (top-10 per division/phase)Viewer can't follow the show without this
Division indicatorShow structure clarity
Per-rider intro card (LITE version — name/country/horse only, no portrait)Identifies who's on
Per-rider stopwatchOperational (atomic-swap fidelity lost; manual cut acceptable)
SJ fault/refusal indicatorInformation contract
SJ Timer scorebug (static fault/time card variant)Information contract

AE-only acceptable (no Captivate twin)

  • XC opener, EOD wrap, story package, replay bumper, 50th-anniversary stings, anything cinematic > 2s.

Rationale: In fallback mode, the show loses gloss but keeps the viewer informed. Bumpers and openers are sacrificable; the scoreboard is not.


Risk Flags (19 days to Day 1)

RiskSeverityWhyMitigation
Course-map graphic with live position dots (Tier-2)HIGHNo TPS feed for Bromont. Position data has to come from either manual operator scrubbing (driven off POC chatter from XC ops on the ground) or Claude CV detection on the Mac Mini — neither is built. Tier-2 only.Do NOT cut into Tier-1 time. If Tier-1 isn't fully done by 2026-05-30, drop entirely.
Per-rider intro cards across ~6 divisions × ~30 riders each = ~180 batch rendersMEDIUMAE batch-render time + roster late-arriving. One template serves dressage + SJ.Render in batches per division as roster firms. Build template once; data-merge automated. Reserve 2026-06-02 EOD as final-batch day.
EN/FR bilingual pre-typesettingMEDIUMFrench strings ~20% longer; lower-thirds need truncation allowance designed inDecide language policy now: bilingual stacked? alternating? Or EN-only broadcast graphics with FR-only social cutdowns? Confirm with Sue Ockendon.
50th-anniversary lockup is a placeholder in brand packMEDIUMWithout ratified anniversary art, the XC opener has a holeConfirm by 2026-05-23 whether anniversary is on-broadcast or dropped. If dropped, simplify XC opener.
SJ Timer re-skin to Bromont brandLOWPrototype already lives at sj-timer.schifftacular.com on Tryon skinToken swap from Tryon → Bromont brand pack. Allow 1 dev-day.
Story package template requires editorial content (rider features)LOWHank's cam crew + Mark must commit to specific riders for featuresConfirm 3-5 feature riders by 2026-05-26. Don't try to feature everyone.
Atomic primary-slot swap on chassis (stopwatch + name + nationality)LOW–MEDIUMLocked design pattern; SPX-GC must hold ms-accurate state across two riders being switchedTest on console in dev rig by 2026-05-25 with simulated operator-driven start events (no TPS — Bromont is manual).
AE-MCP wrapInTransaction=false quirkLOWKnown footgun — silently rolls back edits when default trueAll AE-MCP execute_script calls in template authoring scripts pass wrapInTransaction=false and manage their own undoGroup. Documented in [[feedback_ae_mcp_wrap_in_transaction]].

Build order (suggested, 19 days)

  1. Days 1-3 (2026-05-17 → 2026-05-19): Asset gathering sprint. Title-sponsor lockup, anniversary art (decision), rider portraits, roster, fonts. Brand pack ratified.
  2. Days 4-7 (2026-05-20 → 2026-05-23): SPX-GC templates — corner bug fallback, lower-third (name/country/horse), lower-third (score/penalties), leaderboard, division indicator, SJ fault/refusal indicator, per-rider stopwatch chassis. Captivate twins built in parallel by same operator.
  3. Days 8-11 (2026-05-24 → 2026-05-27): AE primary work — intro card template (data-merge driven, serves dressage + SJ), replay bumper, EOD wrap. SJ Timer re-skin to Bromont brand. Begin XC layout scene_config.yaml for the 4 OBS scenes (HERO, START BOX PiP, REPLAY + LIVE, LEADERBOARD + INSET).
  4. Days 12-14 (2026-05-28 → 2026-05-30): XC opener (B-roll edit + anniversary title card), story package template. Integration testing: operator console → SPX-GC + AE media triggers. Primary-slot atomic-swap test on stopwatch.
  5. Days 15-17 (2026-05-31 → 2026-06-02): Rehearsal with operator. Batch-render all intro cards across divisions. Captivate fallback drill — operator runs a mock segment with primary rig "dead."
  6. Days 18-19 (2026-06-03 → 2026-06-04): On-site setup, fence broll capture for XC opener cut-ins, dress rehearsal, Day 1 go-live.

Tier-2 graphics enter the schedule only if Tier-1 hits a clean checkpoint by 2026-05-30. Otherwise, defer.


This plan respects the locked scope. No version-2 features. No CMH/H&C lockups. Bromont brand only. YouTube Live only. AE+SPX primary, Captivate fallback. Operator-menu-driven. Build directly from this in the morning.

Source: broadcast/shows/bromont-2026-06/production-plan/GRAPHICS-BUILD-PLAN.md