Skip to main content
Deploy
Migrating to HyperFrames Lambda
Side-by-side mapping for adopters coming to HyperFrames from another one-command-deploy video renderer.
If you’re already running a different framework that deploys a serverless video renderer with one command, the muscle memory translates cleanly: a single
For framework-agnostic animation, HyperFrames supports first-party adapters for GSAP, Anime.js, CSS keyframes, Lottie, Three.js, and the Web Animations API — covered in the Concepts and per-skill docs.
deploy provisions the stack, a single render starts a render, a single progress polls it, and a single destroy tears the stack down. This page maps your existing concepts onto HyperFrames’ equivalents so you can spend the migration on the parts that actually differ instead of relearning the workflow.
Concept mapping
Composition format
If your current framework is React-based, you write JSX components, register them in aComposition, and the renderer compiles them at render time.
In HyperFrames, compositions are plain HTML files. The data-duration, data-width, data-height, and data-fps attributes on the root element drive every render parameter. There is no JSX compilation step — what you write is what the browser renders.
Render config
Most adopters’ render config maps directly:Variables (inputProps)
Render-time payloads —inputProps in some frameworks, variables in HyperFrames — are isomorphic. Declare the composition’s variable shape on the root <html> element via data-composition-variables, then pass per-render values with hyperframes render --variables '{...}' locally or hyperframes lambda render --variables on the Lambda surface. The same 256 KiB execution-input cap and “URL your assets, don’t inline base64” convention apply.
The full mapping — defaultProps → declarations, useCurrentFrame() + props.<x> → __hyperframes.getVariables().<x>, renderMediaOnLambda({ inputProps }) → renderToLambda({ config: { variables } }) — lives in Templates on Lambda.
What HyperFrames does differently
A few areas where the contract is intentionally different from comparable frameworks. Surface them up front so the migration doesn’t surprise you mid-deploy.Deterministic Chrome path is mandatory
HyperFrames refusesdata-gpu-mode="hardware" in distributed mode — hardware GL is non-deterministic across chunk boundaries, and the per-chunk concat-copy assumes byte-level reproducibility. Compositions that opt into hardware GL in-process must drop it for Lambda renders. The Lambda handler trips a typed BROWSER_GPU_NOT_SOFTWARE non-retryable error on plan that’s easy to catch in the progress output.
Font fetching fails closed
failClosedFontFetch is default-on in distributed mode. A composition that references a font-family HyperFrames can’t fetch will fail at plan time (FONT_FETCH_FAILED) rather than silently falling back to the OS default. If you currently lean on system-font fallbacks, list the fonts you need explicitly via <link rel="stylesheet"> or @fontsource/* imports.
No HDR (yet)
hdrMode: 'force-hdr' is rejected at plan time. The v1.5 backlog covers HDR mp4 via -bsf:v hevc_metadata re-application; for now, HDR renders use the in-process renderer outside Lambda.
webm uses closed-GOP VP9
webm distributed renders go through libvpx-vp9 with-g <chunkSize>, -keyint_min <chunkSize>, -auto-alt-ref 0, and -cpu-used 4 by default. The alt-ref disable is the load-bearing bit: libvpx-vp9’s default non-displayable alt-ref frames can land anywhere in a GOP, which breaks concat-copy at chunk seams. Closed-GOP forces a keyframe at every chunk boundary so ffmpeg -f concat -c copy round-trips losslessly. Output is yuva420p to preserve alpha. Audio is muxed as Opus.
Distributed webm files are typically ~10-25% larger than the same composition rendered in-process at the same CRF, because closed-GOP forces more keyframes than the in-process single-pass would emit. VP9 encode speed is controlled by PRODUCER_VP9_CPU_USED (-8 to 8); use lower values for quality-sensitive or long-form WebM, and higher values when wall-clock encode time matters more than compression efficiency. The single-machine in-process renderer remains the right choice for short webm renders; distributed pays for itself once a render’s wall-clock exceeds what one machine delivers.
State files are local by default
hyperframes lambda deploy writes <cwd>/.hyperframes/lambda-stack-<name>.json so subsequent verbs don’t re-derive the bucket / state-machine ARN. Two worktrees produce two distinct state files. If you need a shared default location across CI workers, symlink the directory or pass --stack-name explicitly on every call.
IAM policy is print-then-narrow
The default policy doc emitted byhyperframes lambda policies user/role uses Resource: "*" because the CloudFormation stack creates new ARNs on every adopter’s first deploy. After your first successful deploy, narrow the Resource to the deployed ARNs — they’re predictable from the CFN outputs. CI users typically check the narrowed policy into source and run hyperframes lambda policies validate ./infra/policy.json as a pre-deploy gate.
Migration checklist
- Inventory the compositions you want to migrate. Filter out anything that needs HDR — that stays on your current framework for now. webm renders distributed via closed-GOP VP9 + concat-copy (see the webm section above).
- Translate each composition to plain HTML. The
[Concepts](/concepts)page covers the data-attribute conventions; installing the skills (npx skills add heygen-com/hyperframes) makes Claude / Cursor / Codex aware of them too — start at/hyperframes, which routes to/hyperframes-corefor the composition contract. - Wire the new composition into your build pipeline alongside the old one. HyperFrames doesn’t need an external bundler — you can
npx hyperframes previewagainst the HTML directly. - Deploy in a separate AWS account or with a
--stack-name=hyperframes-stagingfirst. Run a real render with--wait; verify the output bytes. - Add the policy to your CI.
hyperframes lambda policies user > infra/iam/hyperframes.jsonthenhyperframes lambda policies validate infra/iam/hyperframes.jsonon every PR. - Cut over by pointing your existing automation at the new render endpoint. Keep the old deployment alive until you’ve verified rolling renders for a release cycle, then
hyperframes lambda destroythe staging stack and decommission the previous one.
Non-Lambda runtimes
If you don’t want Lambda specifically, the same@hyperframes/producer/distributed primitives run anywhere Node + Chrome + ffmpeg + S3 are available. A reference Dockerfile lives at examples/k8s-jobs/Dockerfile.example for adopters running on:
- Google Cloud Run Jobs
- Azure Container Apps Jobs
- AWS ECS Fargate
- Kubernetes Jobs / Argo Workflows
- Plain Docker on a beefy VM
