chore: import upstream snapshot with attribution
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
Docs / Validate docs (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Sync skills to ClawHub / Publish changed skills (push) Waiting to run
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:58:35 +08:00
commit 85453da49f
4031 changed files with 710987 additions and 0 deletions
+227
View File
@@ -0,0 +1,227 @@
# AWS Lambda + Step Functions deployment
Reference SAM template for deploying HyperFrames distributed rendering on
AWS. One Lambda function, three roles (Plan / RenderChunk / Assemble),
choreographed by a Step Functions standard workflow with a Map state for
parallel chunk rendering.
See [`packages/aws-lambda/README.md`](../../packages/aws-lambda/README.md)
for the Lambda handler architecture.
## Prerequisites
- AWS account with IAM permissions to deploy CloudFormation stacks
containing Lambda, Step Functions, S3, IAM, and CloudWatch resources.
- [`sam` CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)
installed (≥ 1.100).
- [`bun`](https://bun.sh) installed (≥ 1.3) to build the handler ZIP.
## One-shot deploy
```bash
# 1. Build the handler ZIP that `template.yaml`'s CodeUri points at.
bun install # at repo root
bun run --cwd packages/aws-lambda build:zip
# 2. Deploy. First time: `--guided` to set stack name + region.
cd examples/aws-lambda
sam deploy --guided --resolve-s3
```
`--resolve-s3` lets SAM pick (or create) a per-account bucket to host the
uploaded ZIP. After the first deploy, subsequent updates can omit
`--guided` and `--resolve-s3` — SAM remembers your choices in
`samconfig.toml`.
## What gets created
| Resource | Purpose |
| ---------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `Render Lambda` | Single function, handler `handler.handler`. Dispatches on `event.Action`. |
| `Render State Machine` | Step Functions standard workflow. Plan → Map(N) RenderChunk → Assemble. |
| `Render Bucket` | S3 bucket for plan tarballs, chunk outputs, and final mp4. `renders/` prefix expires after 7 days. |
| IAM role for the state machine | Invokes the Lambda; writes CloudWatch logs; X-Ray traces. |
| IAM role for the Lambda (managed by SAM) | S3 CRUD on the render bucket; CloudWatch logs. |
| Runaway-invocation alarm | Fires if RenderChunk runs more than `ChunkInvocationAlarmThreshold` times in an hour. |
## Running a render
Upload your project as a zip to the render bucket, then start a Step
Functions execution:
```bash
STACK_NAME=hyperframes-render # whatever you picked at deploy
RENDER_BUCKET=$(aws cloudformation describe-stacks \
--stack-name "$STACK_NAME" \
--query 'Stacks[0].Outputs[?OutputKey==`RenderBucketName`].OutputValue' \
--output text)
STATE_MACHINE_ARN=$(aws cloudformation describe-stacks \
--stack-name "$STACK_NAME" \
--query 'Stacks[0].Outputs[?OutputKey==`RenderStateMachineArn`].OutputValue' \
--output text)
# Tar + upload the project directory. The handler uses `tar` (not
# `unzip`, which Lambda's base image doesn't ship), so the on-the-wire
# archive format is `.tar.gz`.
tar -czf my-project.tar.gz -C ./my-project .
aws s3 cp my-project.tar.gz "s3://${RENDER_BUCKET}/projects/my-project.tar.gz"
# Start the execution. The input JSON tells the state machine where to
# read inputs and write outputs.
aws stepfunctions start-execution \
--state-machine-arn "$STATE_MACHINE_ARN" \
--input "$(cat <<EOF
{
"ProjectS3Uri": "s3://${RENDER_BUCKET}/projects/my-project.tar.gz",
"PlanOutputS3Prefix": "s3://${RENDER_BUCKET}/renders/$(date +%s)/",
"OutputS3Uri": "s3://${RENDER_BUCKET}/output.mp4",
"Config": {
"fps": 30,
"width": 1920,
"height": 1080,
"format": "mp4",
"chunkSize": 240,
"maxParallelChunks": 8,
"runtimeCap": "lambda"
}
}
EOF
)"
```
The Step Functions execution kicks off Plan, fans out RenderChunk via
the Map state, and finally Assemble. Final mp4 lands at `OutputS3Uri`.
## Local invocation
You can test the Lambda handler without deploying anything via SAM
local:
```bash
# Build the ZIP first.
bun run --cwd packages/aws-lambda build:zip
# Launch a local Lambda runtime emulator and run a sample plan event.
cd examples/aws-lambda
sam validate
sam local invoke RenderFunction --event sample-events/plan.json
```
The `sample-events/` directory ships small JSON payloads for each of the
three actions. They reference fake S3 URIs — useful for sanity-checking
the handler's dispatch logic; not for full end-to-end testing (real S3
calls require credentials and a project zip to actually exist).
## End-to-end smoke + benchmark
For full end-to-end validation against real AWS — the gate that proves
the architecture works on a deployed Lambda — use the local smoke
script:
```bash
# All defaults (mp4-h264-sdr fixture, chunk counts 2/4/8, PSNR >= 40 dB).
./scripts/smoke.sh
# Customised:
./scripts/smoke.sh \
--fixture mp4-h264-sdr \
--chunk-counts 2,4,8,16 \
--psnr-threshold 40 \
--reserved-concurrency 8
# Keep the stack alive for inspection afterward:
./scripts/smoke.sh --keep-stack
# Show all flags including cost notes:
./scripts/smoke.sh --help
```
The script builds the handler ZIP, deploys this template under a
per-run stack name, renders the fixture at each chunk count via the
Step Functions state machine, PSNR-compares against the in-process
baseline (which is git-LFS tracked under
`packages/producer/tests/distributed/<fixture>/output/`), captures
per-execution Step Functions history, and tears the stack down.
**Wall-clock methodology caveat (`eval.sh` only).** `eval.sh` reports a
local-vs-Lambda "speedup" column. The local timing includes `bun` +
`tsx` + harness scaffolding (not just renderer-internal time); the
Lambda timing measures Step Functions execution only. This biases the
speedup against Lambda on tiny fixtures and in favour of Lambda on
larger ones. Treat the number as "end-to-end CLI experience," not as a
renderer-vs-renderer benchmark. Cold-start variance is ±5-10s per
chunk; run with `--iterations 3+` to report medians.
**Cost per pass.** Each `eval.sh` invocation runs `SAM deploy` (~$0.01
in CFN operations) plus N fixtures × ITERATIONS × CHUNK_COUNT Lambda
invocations at `MemorySize` (default 10 GiB) × per-chunk wall clock.
With defaults (4 fixtures, 1 iteration, chunk-count 4) the Lambda
spend is roughly $0.10-$0.20 per pass before S3 transfer. Lower
`--reserved-concurrency` for cost-conscious accounts; higher
`--iterations` improves median stability at proportional cost.
Outputs land under `<repo-root>/lambda-smoke-artifacts/`:
- `results.json``chunkCount × wallClockMs × psnrAvgDb`
- `renders/N<N>-output.mp4` — each rendered chunk count
- `renders/N<N>-history.json` — full Step Functions execution history
Prerequisites: `aws` (v2), `sam` (≥ 1.100), `bun` (≥ 1.3), `ffmpeg`,
`jq`, `zip`. AWS credentials come from the standard resolution chain
(env vars → `~/.aws/credentials` → SSO → IMDS). Pin a specific profile
with `--profile <name>` or `AWS_PROFILE=<name>`.
## Parameters
| Parameter | Default | Notes |
| ------------------------------- | ------------- | ----------------------------------------------------------------------------------------------- |
| `ProjectName` | `hyperframes` | Prefix for created resource names. |
| `LambdaMemoryMb` | `10240` | Lambda memory; Lambda allocates CPU proportionally. 10 GB recommended for 1080p. |
| `LambdaTimeoutSec` | `900` | Per-invocation timeout. 15 min is Lambda's hard ceiling. |
| `ReservedConcurrency` | `-1` | Hard cap on simultaneous Lambda invocations. `-1` = unreserved. Set to e.g. `50` to bound cost. |
| `ChromeSource` | `sparticuz` | Must match the `--source=` flag passed to `build-zip.ts`. |
| `ChunkInvocationAlarmThreshold` | `1000` | CloudWatch alarm threshold (RenderChunk invocations per hour). |
## Cleanup
```bash
sam delete --stack-name hyperframes-render
```
S3 buckets are `Retain`ed on delete to protect rendered artifacts.
Empty + delete the bucket manually after `sam delete` if you want to
fully tear down.
## Cost model
| Service | Driver | Approximate cost |
| ----------------------- | --------------------------------------- | -------------------------------------------------------------- |
| Lambda | Per-invocation billed duration × memory | ≈ $0.0000167/GB-s; a 10 GB function running 5 min costs ~$0.50 |
| Step Functions Standard | Per state transition | $0.025/1k transitions |
| S3 | Storage + GET/PUT | Dominated by mp4 storage; plan tarballs expire in 7 days |
| CloudWatch Logs | Ingestion + storage | Logs are not throttled; set retention manually if cost matters |
A 60-second 1080p30 composition at default chunkSize=240 (8 chunks)
typically costs ~$0.04 in Lambda time + ~$0.001 in Step Functions.
The eval script under `scripts/eval.sh` produces real per-fixture cost
numbers when you run it against your own AWS account.
## Troubleshooting
- **"Chrome failed to launch"** — the ZIP was likely built with the wrong
`--source`. Match `ChromeSource` to the build flag.
- **"PLAN_HASH_MISMATCH"** — non-retryable. The plan tarball was written
by a different version of the producer than the chunk worker is
running. Re-plan from scratch.
- **"BROWSER_GPU_NOT_SOFTWARE"** — Chromium fell back to a hardware GL
backend. Should not happen in Lambda (no GPU); file an issue.
- **CloudWatch alarm firing on `runaway-chunk-invocations`** — check
the state machine execution history for an unintended Map fan-out, or
raise the threshold if your workload genuinely exceeds it.
## What's NOT in this directory
- CDK construct shipping the same topology programmatically — follow-up.
- `hyperframes lambda deploy / render / progress / destroy` CLI — follow-up.
- Migration guide — follow-up.
- Lambda RIE local smoke harness mode — follow-up.