mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-01 19:42:03 +00:00
* feat(lambda): add Lambda handler, ZIP bundling, and BeginFrame probe
Phase 6 of the distributed rendering plan: AWS Lambda turnkey adoption
(see DISTRIBUTED-RENDERING-PLAN.md §11 Phase 6 + §15).
This PR adds the new packages/aws-lambda/ workspace package that wraps
the OSS plan/renderChunk/assemble primitives in an AWS Lambda handler,
plus a build pipeline that bundles the handler + Chromium runtime +
ffmpeg into a deployable ZIP.
Architecture: ZIP deploy (not Docker image), Chrome via @sparticuz/chromium
with chrome-headless-shell fallback, dispatch on event.Action ∈ {plan,
renderChunk, assemble}.
The load-bearing concern — does @sparticuz/chromium's chrome-headless-shell
build honour CDP HeadlessExperimental.beginFrame? — is pinned by the new
scripts/probe-beginframe.ts regression guard. Probe boots the runtime
inside public.ecr.aws/lambda/nodejs:22, navigates to a static page, and
asserts beginFrame returns a PNG buffer. Verified locally + inside the
Docker container; both pass with hasDamage=true.
Sizes (sparticuz source): unzipped 157 MiB, zipped 99 MiB. Well under
the 240 MiB / 150 MiB in-house gates and the Lambda 250 MiB hard ceiling.
This is part of a stack of 8 PRs (3 in Phase 6a, 5 in Phase 6b); this is
PR 6.1.
* fix(lambda): address PR 878 review feedback
- Verify event.PlanHash against the untarred plan.json at the handler
boundary before invoking the producer primitive. Throws typed
PLAN_HASH_MISMATCH on divergence so Step Functions routes it as
non-retryable; previously the field was schema bloat the handler
ignored, leaving enforcement entirely inside the producer.
- Standardize on MiB throughout build-zip.ts, verify-zip-size.ts, and
the README. Lambda's hard ceiling is 250 MiB (AWS docs label "250 MB"
but use binary mebibytes); previously mixed units made the 248 MiB
budget look like a ~5 MB margin instead of the 2 MiB it actually is.
- stageChromeHeadlessShell now picks Chrome versions via numeric semver
comparison instead of lexicographic sort+reverse — the latter would
silently pick "99.x" over "131.x" once Chrome cached three-digit
majors that aren't width-aligned.
- Drop _setSparticuzChromiumForTests from the public index barrel.
Test-only DI seam imported directly from ./chromium.js in tests.
- Replace require("node:fs") inside walkSize() with the top-level fs
imports — file is ESM and the same module is already imported.
* docs(lambda): drop internal plan-doc refs from package README
* ci(windows): fix bun filter UNION bug excluding producer from Windows tests
`bun run --filter "!a" --filter "!b" test` composes as a UNION (any
package matching either negation runs), not an intersection. Effect:
@hyperframes/producer was still being tested on Windows even though
it's explicitly excluded — its regression harness (Docker + LFS golden
mp4 baselines) is Linux-only and was driving the 32min timeout.
Enumerate the packages we DO want to test instead.
93 lines
3.3 KiB
Docker
93 lines
3.3 KiB
Docker
# HyperFrames Producer - Regression Test Image
|
|
#
|
|
# Matches the production rendering environment (same Chromium, fonts, FFmpeg)
|
|
# but includes the full source + devDependencies for running the test harness.
|
|
#
|
|
# This ensures golden baselines match what production actually renders.
|
|
#
|
|
# Usage:
|
|
# docker build -f Dockerfile.test -t hyperframes-producer:test .
|
|
# docker run --rm -v ./packages/producer/tests:/app/packages/producer/tests hyperframes-producer:test
|
|
# docker run --rm -v ./packages/producer/tests:/app/packages/producer/tests hyperframes-producer:test --update
|
|
|
|
FROM node:22-bookworm-slim
|
|
|
|
# ── System dependencies (identical to production) ────────────────────────────
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
ca-certificates \
|
|
curl \
|
|
unzip \
|
|
ffmpeg \
|
|
chromium \
|
|
libgbm1 \
|
|
libnss3 \
|
|
libatk-bridge2.0-0 \
|
|
libdrm2 \
|
|
libxcomposite1 \
|
|
libxdamage1 \
|
|
libxrandr2 \
|
|
libcups2 \
|
|
libasound2 \
|
|
libpangocairo-1.0-0 \
|
|
libxshmfence1 \
|
|
libgtk-3-0 \
|
|
# Font support — matches production
|
|
fonts-liberation \
|
|
fonts-noto-color-emoji \
|
|
fonts-noto-cjk \
|
|
fonts-noto-core \
|
|
fonts-noto-extra \
|
|
fonts-noto-ui-core \
|
|
fonts-freefont-ttf \
|
|
fonts-dejavu-core \
|
|
fontconfig \
|
|
&& rm -rf /var/lib/apt/lists/* \
|
|
&& apt-get clean \
|
|
&& fc-cache -fv
|
|
|
|
# Use system Chromium (same as production)
|
|
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
|
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium
|
|
ENV CONTAINER=true
|
|
|
|
# Install chrome-headless-shell for deterministic BeginFrame rendering.
|
|
# This lightweight Chrome binary supports HeadlessExperimental.beginFrame.
|
|
# Install to ~/.cache/puppeteer/ where resolveHeadlessShellPath() looks.
|
|
RUN npx --yes @puppeteer/browsers install chrome-headless-shell@stable \
|
|
--path /root/.cache/puppeteer \
|
|
&& find /root/.cache/puppeteer/chrome-headless-shell -name "chrome-headless-shell" -type f \
|
|
&& echo "chrome-headless-shell installed"
|
|
|
|
WORKDIR /app
|
|
|
|
# Install bun
|
|
RUN curl -fsSL https://bun.sh/install | bash
|
|
ENV PATH="/root/.bun/bin:$PATH"
|
|
|
|
# Install dependencies (full, including devDependencies for tsx + test harness)
|
|
COPY package.json bun.lock ./
|
|
COPY packages/core/package.json packages/core/package.json
|
|
COPY packages/engine/package.json packages/engine/package.json
|
|
COPY packages/player/package.json packages/player/package.json
|
|
COPY packages/producer/package.json packages/producer/package.json
|
|
COPY packages/cli/package.json packages/cli/package.json
|
|
COPY packages/studio/package.json packages/studio/package.json
|
|
COPY packages/shader-transitions/package.json packages/shader-transitions/package.json
|
|
COPY packages/aws-lambda/package.json packages/aws-lambda/package.json
|
|
RUN bun install --frozen-lockfile
|
|
|
|
# Copy source
|
|
COPY packages/core/ packages/core/
|
|
COPY packages/engine/ packages/engine/
|
|
COPY packages/producer/ packages/producer/
|
|
|
|
# Build core runtime artifacts (needed by renderer)
|
|
RUN bun run --filter @hyperframes/core build:hyperframes-runtime:modular
|
|
|
|
# Generate embedded font data (deterministicFonts.ts imports this at runtime)
|
|
RUN cd packages/producer && bunx tsx scripts/generate-font-data.ts
|
|
|
|
WORKDIR /app/packages/producer
|
|
|
|
ENTRYPOINT ["bunx", "tsx", "src/regression-harness.ts", "--", "--sequential"]
|