From 480d0cfa5aa4667cecc0964008b4183a535e5b21 Mon Sep 17 00:00:00 2001 From: James Date: Tue, 19 May 2026 19:52:39 +0000 Subject: [PATCH] docs(deploy): templates-on-lambda guide for personalised video at scale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User-facing guide for the automated template-rendering pipeline now shippable end-to-end after PRs 9.1-9.4: - What a template is (composition + data-composition-variables) - Declaring variables (syntax, types, defaults, getVariables()) - Local iteration loop (hyperframes render --variables / --variables-file / --strict-variables) - Deploying to Lambda (pointers to deploy guide + sites create) - Single personalised render (lambda render --variables) - Batch pipeline (lambda render-batch --batch users.jsonl, with a worked 5-row example, manifest output, progress polling, --dry-run) - Programmatic via SDK (TypeScript example with deploySite + Promise.all(renderToLambda)) - Working with large variables (the 256 KiB Step Functions ceiling, URL-your-assets convention, the one-line escape note for genuine >256 KiB cases) - Cost + scale considerations (Lambda concurrency, max-parallel-chunks vs max-concurrent, in-process vs distributed crossover) - Migrating from @remotion/lambda inputProps (side-by-side table; same 256 KiB cap and same URL-your-assets convention, so migration is mechanical) Includes a Mermaid architecture diagram for the site-upload-once + N-execution fan-out flow at the top. Adds the guide to the Deploy navigation group in docs.json (between the existing aws-lambda and migrating-to-hyperframes-lambda pages). Phase 9 PR 9.5 of the distributed rendering plan — the load-bearing artifact for the user-facing pitch. --- docs/deploy/templates-on-lambda.mdx | 319 ++++++++++++++++++++++++++++ docs/docs.json | 1 + 2 files changed, 320 insertions(+) create mode 100644 docs/deploy/templates-on-lambda.mdx diff --git a/docs/deploy/templates-on-lambda.mdx b/docs/deploy/templates-on-lambda.mdx new file mode 100644 index 000000000..efe2dc143 --- /dev/null +++ b/docs/deploy/templates-on-lambda.mdx @@ -0,0 +1,319 @@ +--- +title: Templates on Lambda +description: "Render personalised template videos at scale on AWS Lambda using --variables and the lambda render-batch verb." +--- + +HyperFrames templates are compositions that take typed variables — a name, a colour, a chart payload, a CTA URL — and produce a finished render parameterised by those values. Pair a template with the deployed Lambda stack and `lambda render-batch`, and you get personalised-video-at-scale in one CLI call: + +```bash +hyperframes lambda render-batch ./my-template \ + --batch ./users.jsonl \ + --width 1920 --height 1080 +``` + +This guide walks the full loop: declare variables on a composition, iterate locally with `hyperframes render`, deploy to Lambda once, then fan out N renders from a batch file. The same flow also drives single personalised renders via `lambda render --variables` and programmatic batches via `renderToLambda({ variables })`. + +```mermaid +flowchart LR + A["Local iteration
hyperframes render --variables"] --> B["Deploy stack
hyperframes lambda deploy"] + B --> C["Upload site once
hyperframes lambda sites create"] + C --> D["Fan out renders
hyperframes lambda render-batch"] + D --> E["N personalised videos
in S3"] +``` + +## What's a template + +A template is just a HyperFrames composition whose top-level HTML element declares a `data-composition-variables` attribute listing the variables it accepts. The composition reads the runtime values via `window.__hyperframes.getVariables()`. + +```html + + +Welcome template + +
+

Welcome

+
+ +
+ + + +``` + +The runtime helper is exposed as a global — `window.__hyperframes.getVariables()` — not as a fetchable module. Use a plain ` +``` + +The same constraint applies to Remotion's `inputProps` — if you're migrating from `@remotion/lambda`, your payloads should already be structured this way. + +If your typed-data payload genuinely exceeds 256 KiB (e.g. a long structured record per render with no media), [file an issue](https://github.com/heygen-com/hyperframes/issues/new) — there's a clean path via S3-hosted variable files, but we want to see real demand before designing the API. + +## Cost and scale + +Each personalised render is one Step Functions execution + N chunk Lambda invocations. At default settings (`chunkSize: 240`, `maxParallelChunks: 16`) a 5-second 30fps composition is 1 chunk; a 60-second composition is ~8 chunks. + +The cost knobs: + +- **`--max-parallel-chunks`**: per render, default 16. Smaller compositions don't fan out beyond `ceil(totalFrames / chunkSize)`. Higher values pay more Lambda invocations but finish faster. +- **Lambda reserved concurrency** (`lambda deploy --concurrency=`): caps how many Lambda invocations the render function can run in parallel. Other workloads in the same AWS account share the same account-level concurrency pool (~1 000 in most regions by default), so reserved concurrency keeps the render function from starving them and vice-versa. +- **`render-batch --max-concurrent`**: orchestrator-side. Caps how many `StartExecution` calls run simultaneously — distinct from the Lambda concurrency cap, which lives one level below at the chunk-invoke layer. The CLI cannot enforce Lambda's account limit; it can only avoid creating excess Step Functions executions queued against it. +- **Lambda memory** (`lambda deploy --memory`): default 10 240 MB (max). Higher memory buys faster Chrome capture + more vCPUs per chunk; lower memory saves cost but risks `15 min` timeouts on heavy compositions. + +Each Step Functions execution fans out to ~`maxParallelChunks` Lambda invocations. So if the deployed reserved concurrency is 8 and `maxParallelChunks` stays at the 16 default, even a single render will get throttled — bump the deploy concurrency before running large batches. + +For small batches (< 100 entries) the default `--max-concurrent 50` is fine. For large batches (> 1 000), a useful starting point is `--max-concurrent ≈ floor(reservedConcurrency / maxParallelChunks)` so each running render gets its full chunk fan-out budget; the batch verb does NOT enforce this, it's just guidance for picking the flag value. + +In-process vs distributed crossover: for a single render under ~30 seconds, the in-process renderer (`hyperframes render`) wins on latency because there's no S3 round-trip per chunk. Distributed wins for renders over ~60 seconds or when you need a personalised batch — that's the whole reason this surface exists. (The Phase 7 small-render shortcut, when it lands, will collapse the gap for short renders.) + +## Migrating from @remotion/lambda inputProps + +Remotion's `inputProps` API and HyperFrames' `variables` are isomorphic — both are JSON objects injected as render-time overrides on top of declared composition defaults. The mapping is mechanical: + +| Remotion | HyperFrames | +|----------|-------------| +| `Composition.defaultProps` | `data-composition-variables` declaration on the root HTML element | +| `useCurrentFrame()` + `props.` | `window.__hyperframes.getVariables().` (read once on DOMContentLoaded) | +| `renderMediaOnLambda({ inputProps })` | `renderToLambda({ config: { variables } })` | +| Lambda inputProps 256 KiB cap | Step Functions execution-input 256 KiB cap | +| inputProps URL'ing pattern for large media | Same convention — URL references, not inlined bytes | + +Remotion's `inputProps` has the same 256 KiB constraint and the same "URL your assets" convention, so a migration of a working `inputProps` pipeline is a straightforward CLI/SDK swap, not a payload reshape. + +## What's next + +- **Smaller batch primitives**: HTML-form input alongside JSONL. Open an issue if you'd find this useful. +- **TypeScript types generated from `data-composition-variables`**: `hyperframes types generate ` is sketched and may land in v1.5; it would let SDK callers `import type { Variables } from "./template/variables"` for autocomplete + typecheck. +- **HDR template support**: HDR mp4 is currently distributed-mode-rejected (in-process only). The next v1.5 item is unblocking HDR for distributed renders so templates can produce wide-gamut output. + +If your template pipeline hits a wall the docs don't cover, [file an issue on GitHub](https://github.com/heygen-com/hyperframes/issues/new) — the batch surface is new and the feedback loop on it is short. diff --git a/docs/docs.json b/docs/docs.json index cfe704ff5..d07dabdc6 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -245,6 +245,7 @@ "group": "Deploy", "pages": [ "deploy/aws-lambda", + "deploy/templates-on-lambda", "deploy/migrating-to-hyperframes-lambda" ] }