Video Overlay Lambda
Last Updated: 2026-07-21
The Video Overlay Lambda burns the flight telemetry instrument band into an
uploaded on-board video, and — before that — builds the browser-playable proxy
the sync wizard scrubs. It is a thin wrapper around core.ts, the same function
the local CLI calls. The web-app UI that drives it is the
Flight Deck; the render model it reuses is the
overlay pipeline.
What it does
The handler (src/index.ts) runs one of two modes, chosen by event.mode:
proxy— runs first, straight after upload. It makes a small, browser-playable H.264 copy of the whole recording (the raw camera file is Motion JPEG in AVI and no browser can decode it), preserving the source's timeline exactly. It is variant/chunk-agnostic and ends the job atAWAITING_SYNC, parked on a human to find the liftoff frame.render— runs once liftoff is marked, and burns the overlay onto the source. It is the default whenmodeis absent (event.mode ?? 'render') — a deliberate back-compat default so an in-flight event enqueued by a previous version of the app, which carried no mode, still means render.
The Lambda is invoked directly by a server action (InvocationType: 'Event', fire-and-forget), not by an S3 notification, and it reports progress by
writing the RenderJob node — the web client polls that node
for status.
Telemetry & the shared model
Telemetry is fetched inside the Lambda (fetchOverlayInput(flightId) in
flights.ts), not passed in. The render then reuses the shared
@rocket-club/flight-overlay model — the same buildOverlayModel →
computeLayout → drawOverlayFrame pipeline (and resolveChunk for the chunk
window) that the browser preview uses — so the burned-in pixels match the preview
by construction. See the overlay pipeline for that
"one renderer, three hosts" contract.
Trim arithmetic
src/trim.ts maps the flight's timeline onto the source video's. Two clocks are
in play:
- Flight time — seconds since detected liftoff,
t = 0. Everything in the telemetry and the overlay model uses this. - Source time — seconds into the uploaded file.
liftoffVideoTimeS (from the sync wizard) is the only bridge between them:
sourceTime = liftoffVideoTimeS + flightTime
computeTrimPlan trims the source to the selected chunk window rather than
the whole flight. The chunk bounds chunkStartS / chunkEndS are optional
and default to today's full window (chunkStartS → overlayStartS,
chunkEndS → landingT), so omitting them — the full chunk — reproduces the
pre-chunk plan byte-for-byte. A named chunk that begins after the camera
already stopped (e.g. descent chosen but the recording died at apogee) is
rejected with a user-facing message rather than producing a broken clip.
Source of truth
- Lambda package:
data/platform/lambda/video-overlay/ - Handler + modes:
data/platform/lambda/video-overlay/src/index.ts - Render core (CLI + Lambda):
data/platform/lambda/video-overlay/src/core.ts - Trim arithmetic:
data/platform/lambda/video-overlay/src/trim.ts - Scrub proxy:
data/platform/lambda/video-overlay/src/proxy.ts