mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 17:27:09 +00:00
* chore(docker): pin FFmpeg 8.0.1 in the Docker images and host CI Install one pinned static BtbN build (n8.0.1-66, month-end release) in Dockerfile.test, the CLI render image, the Cloud Run image and the k8s example, and bump the host CI install-ffmpeg-linux action from 7.1.3 to the same build. Regression baselines and the shipped images now use the same FFmpeg version instead of Debian's apt ffmpeg 5.1. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(producer): regenerate six regression baselines on FFmpeg 8.0.1 The Docker test image now renders with FFmpeg 8.0.1 instead of Debian's 5.1. Six fixtures fail against the 5.1 baselines; everything else passes unchanged, including vfr-screen-recording. - style-2-prod, style-10-prod: FFmpeg 8 honors the MP3 gapless header, so the probed SFX duration is 1.0s instead of 1.044898s. Regenerate output.mp4 and compiled.html. - vignelli-stacking: one checkpoint (8.06s) now shows source frame 201 of the 25fps a-roll, which is the right frame for that time; the old baseline showed frame 202. - missing-host-comp-id, variables-prod, speed-ramp: AAC encoder output differs enough to drop the RMS-envelope correlation on flat signals below 0.9. Sample correlation against the source stays at 0.9999. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cli): read the ffmpeg version from n-prefixed release builds Release-branch ffmpeg builds, including the BtbN build now pinned in CI, print "ffmpeg version n8.0.1-66-...". extractMajorVersion skipped the "n8" token and returned 0 (and 1 for n7.1.3), so the CLI telemetry smoke check failed. parseToolVersion fell back to the whole banner line. Accept an optional "n" before the version number in both. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cli): keep the preflight comment share flat Fold the n-prefix note into the existing doc line instead of adding new comment lines, which the comment ratchet rejects. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(docker): pick the FFmpeg build per arch and fail on a bad binary Dockerfile.test, the k8s example and the Cloud Run image always extracted the amd64 archive on multiarch bases, and the piped version check passed even when the binary could not run. All four images now pick linux64 or linuxarm64 by TARGETARCH, fail on any other arch, and grep both ffmpeg and ffprobe for the pinned version. style-2-prod and style-10-prod compiled.html go back to the previous golden with only the SFX data-duration/data-end changed, instead of a full recompile that also picked up unrelated compiler output. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
163 lines
7.9 KiB
Docker
163 lines
7.9 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.23.3-bookworm-slim
|
|
|
|
# ── System dependencies (identical to production) ────────────────────────────
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
ca-certificates \
|
|
curl \
|
|
unzip \
|
|
xz-utils \
|
|
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
|
|
|
|
# ── FFmpeg (pinned) ──────────────────────────────────────────────────────────
|
|
# One pinned static build (BtbN n8.0.1) instead of Debian's apt ffmpeg, so
|
|
# regression baselines and the shipped images use the same FFmpeg version.
|
|
# Bump the URL and sha256 together, and keep in sync with the other Dockerfiles
|
|
# and .github/actions/install-ffmpeg-linux/action.yml.
|
|
ARG TARGETARCH
|
|
ARG FFMPEG_RELEASE=https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2026-02-28-12-59
|
|
ARG FFMPEG_BUILD=ffmpeg-n8.0.1-66-g27b8d1a017
|
|
ARG FFMPEG_SHA256_AMD64=26d2ecd0cefba99f9d1ea92252a3a4f743a58df4c1c3cf9f8bbaaa40b1fca5b0
|
|
ARG FFMPEG_SHA256_ARM64=d72cc324cb65dd92a9ffe699cc95ccbacfef4def8d3ad9fe2b5164a6a71b9595
|
|
RUN case "$TARGETARCH" in \
|
|
amd64) FF_ARCH=linux64; FF_SHA256="$FFMPEG_SHA256_AMD64" ;; \
|
|
arm64) FF_ARCH=linuxarm64; FF_SHA256="$FFMPEG_SHA256_ARM64" ;; \
|
|
*) echo "unsupported TARGETARCH '$TARGETARCH'" >&2; exit 1 ;; \
|
|
esac \
|
|
&& curl -fsSL -o /tmp/ffmpeg.tar.xz "$FFMPEG_RELEASE/$FFMPEG_BUILD-$FF_ARCH-gpl-8.0.tar.xz" \
|
|
&& echo "$FF_SHA256 /tmp/ffmpeg.tar.xz" | sha256sum -c - \
|
|
&& tar -xJf /tmp/ffmpeg.tar.xz -C /usr/local/bin --strip-components=2 --wildcards '*/bin/ffmpeg' '*/bin/ffprobe' \
|
|
&& rm /tmp/ffmpeg.tar.xz \
|
|
&& ffmpeg -version | grep -F "ffmpeg version ${FFMPEG_BUILD#ffmpeg-}" \
|
|
&& ffprobe -version | grep -F "ffprobe version ${FFMPEG_BUILD#ffmpeg-}"
|
|
|
|
# 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.
|
|
#
|
|
# Pinned to a specific build (NOT @stable) so the regression-test golden
|
|
# baselines in packages/producer/tests/*/output/output.mp4 stay reproducible.
|
|
# Each Chrome stable bump shifts pixel output enough to fail PSNR. Bump this
|
|
# version together with regenerating baselines via `docker:test:update`.
|
|
RUN npx --yes @puppeteer/browsers install chrome-headless-shell@148.0.7778.167 \
|
|
--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 | BUN_INSTALL="/root/.bun" bash -s "bun-v1.3.13"
|
|
ENV PATH="/root/.bun/bin:$PATH"
|
|
|
|
# Install dependencies (full, including devDependencies for tsx + test harness).
|
|
# Every workspace member (packages/*) must be COPYed here — `bun install
|
|
# --frozen-lockfile` treats any member missing from the build context as a
|
|
# lockfile change and fails.
|
|
COPY package.json bun.lock ./
|
|
COPY packages/parsers/package.json packages/parsers/package.json
|
|
COPY packages/lint/package.json packages/lint/package.json
|
|
COPY packages/studio-server/package.json packages/studio-server/package.json
|
|
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
|
|
COPY packages/gcp-cloud-run/package.json packages/gcp-cloud-run/package.json
|
|
COPY packages/sdk/package.json packages/sdk/package.json
|
|
COPY packages/sdk-playground/package.json packages/sdk-playground/package.json
|
|
COPY packages/inspector/package.json packages/inspector/package.json
|
|
# A corrupt tarball extraction (e.g. run 35468046055: "Fail extracting tarball
|
|
# for aws-cdk-lib") can print an error and then hang instead of exiting, once
|
|
# eating a full 60-minute job timeout. Bound each attempt and retry once.
|
|
RUN timeout 300 bun install --frozen-lockfile \
|
|
|| timeout 300 bun install --frozen-lockfile
|
|
|
|
# Copy source in dependency order, running each build as soon as its own
|
|
# inputs are present.
|
|
#
|
|
# Every package used to be copied here before any build ran, which put the
|
|
# `COPY packages/producer/` layer above the core build. Docker invalidates
|
|
# every layer below a changed one, so a producer-only change rebuilt core —
|
|
# which cannot depend on producer. On CI run 30229469233 those two layers
|
|
# cost 86s and 63s of the ~4m image build, in all 8 shards, on every PR.
|
|
# Locally the same producer-only rebuild goes from 18s to 1s after this split.
|
|
#
|
|
# Keep the ordering dependency-correct: anything the core build reads must be
|
|
# copied above it, and packages nothing above depends on stay below.
|
|
COPY packages/parsers/ packages/parsers/
|
|
COPY packages/lint/ packages/lint/
|
|
COPY packages/studio-server/ packages/studio-server/
|
|
COPY packages/core/ packages/core/
|
|
|
|
# Build workspace packages so "node" export conditions resolve to built dist
|
|
RUN bun run --filter '@hyperframes/{parsers,lint,studio-server}' build \
|
|
&& bun run --cwd packages/core build
|
|
|
|
# Build core runtime artifacts (needed by renderer)
|
|
RUN bun run --filter @hyperframes/core build:hyperframes-runtime:modular
|
|
|
|
# Nothing above reads these, so they land after the core build to keep it cached.
|
|
COPY packages/engine/ packages/engine/
|
|
COPY packages/producer/ packages/producer/
|
|
|
|
WORKDIR /app/packages/producer
|
|
|
|
# Skip fixtures tagged `transparency` (Chrome alpha-channel PSNR quirks not
|
|
# reproducible on the CI image), `webgpu` (needs a hardware adapter; CI has
|
|
# only swiftshader, which cannot render canvas WebGPU) and
|
|
# `field-signal-reproducer` (known-broken
|
|
# fixture per PR #2512 — codifies a real bug awaiting a fix). Mirrors the
|
|
# `--exclude-tags` in the local `test:regression*` scripts in
|
|
# packages/producer/package.json so `bun run docker:test*` and the aws-lambda
|
|
# smoke tests skip the same set. Docker CMD args from `docker run <image> ...`
|
|
# are appended after these flags, so positional test names (e.g. shard args
|
|
# `hdr-regression style-5-prod ...` in .github/workflows/regression.yml) still
|
|
# resolve normally; the harness applies excludeTags whether testNames is empty
|
|
# or non-empty (see discoverTestSuites in src/regression-harness.ts).
|
|
ENTRYPOINT ["bunx", "tsx", "src/regression-harness.ts", "--", "--sequential", "--exclude-tags", "transparency,field-signal-reproducer,webgpu"]
|