Repository navigation
build(aws-lambda): pinned native ffmpeg build for an arm64 Lambda image - #6062
Conversation
jrusso1020
left a comment
There was a problem hiding this comment.
Reviewed at f7ec675. The artifact stage depends on the check stage, the source archives are pinned by hash, and the new workflow compares two independent native ARM builds. This is still build-only: none of the five changed files touch deploy or anything that consumes the build at runtime.
P2: build 10-bit x265 and check the encoded pixel format (packages/aws-lambda/image/build-ffmpeg.sh:33-35, packages/aws-lambda/image/check-ffmpeg.sh:43-47).
- The recipe builds 8-bit only. In the pinned x265 4.1, CMake defaults
HIGH_BIT_DEPTHandLINKED_10BITto OFF, and the recipe doesn't override either. - FFmpeg falls back without failing. With no 10/12-bit x265, the pinned FFmpeg 7.0.2 offers only 8-bit formats (
libavcodec/libx265.c:897-904).fftools/ffmpeg_mux_init.c:527-534then picks a supported format and only logs a warning. - The check can't see it.
ff()runs at-loglevel error, so asking foryuv420p10lecan silently produce 8-bit HEVC and still pass the tonemap check. - The engine needs 10-bit. Its HDR encode requires
yuv420p10le(packages/engine/src/services/chunkEncoder.ts:163-169).
Fix: build x265 with 8-bit and 10-bit support, and assert hdr.mp4's actual pix_fmt with ffprobe. A command that succeeds doesn't prove 10-bit.
Since the first requested head (6f55484), the only changes are the renamed recipe and scripts and a change to GnuTLS linkage. The x265 configuration and the HDR check are unchanged. The downloaded x265 and FFmpeg archives match the sources.txt hashes, and the bash syntax checks pass. The base-image digest has both ARM64 and AMD64 manifests.
Not run: a local Docker compile, native ARM codec execution, a Lambda invocation, or the two-build reproducibility check. Whether x264 matches the engine's build is a separate open question I haven't verified.
Review by Rames (hf-review)
|
Thanks, fixed at a51fd1d.
|
jrusso1020
left a comment
There was a problem hiding this comment.
Re-reviewed at a51fd1d against my f7ec675 request for changes. The blocker is fixed: x265 is no longer 8-bit only, and the HDR output format is now checked.
- Build (
packages/aws-lambda/image/build-ffmpeg.sh:33-43): builds the 10-bit library separately (HIGH_BIT_DEPTH=ON,EXPORT_C_API=OFF), links it into the 8-bit build (LINKED_10BIT=ON), and merges both static archives withar -M. This is x265's upstream multilib layout.ENABLE_SVE2=OFFleaves out kernels the base image's gcc 11 can't build. - Check (
check-ffmpeg.sh:46): now requires the probedpix_fmtof the encoded HDR fixture to beyuv420p10le.
What was verified
- Both scripts pass shell syntax checks.
- The new check, run against system-FFmpeg fixtures, rejects 8-bit output and accepts 10-bit. That validates the check itself, not the pinned artifact.
What was not run
- A full Docker, x265 or FFmpeg compile.
- Native ARM execution, a Lambda invocation, or the two-build reproducibility check.
- The ARM and x86 build evidence in the PR is the author's, and CI was not independently confirmed here.
- x264 is now pinned to r3191, but byte parity with the existing x86 binary is still unverified.
This approves the build recipe only. It is not acceptance for release or deployment.
Review by Rames (hf-review)
One recipe, run per architecture on the Lambda Node 22 base it ships on. Codec libraries link statically; glibc and GnuTLS stay dynamic, with the two libraries the bare base lacks bundled beside the binaries. A check stage on the bare base proves every encoder, decoder, filter and protocol the engine calls, and the artifact cannot be produced without it. CI builds it on two ARM runners and requires byte-identical tarballs.
With --static pkg-config flags, gnutls.pc names a libgmp.a from its own RPM build tree and configure rejected GnuTLS. The codec libraries exist only as static archives, so they still link statically. The recipe moves to image/, which will also hold the video function image stage.
x265 builds its SVE2 kernels with -march=armv9-a, which gcc 11 rejects. Turn them off, and stop a failed x265 build from reaching ffmpeg configure as a misleading "x265 not found".
The x86 ffmpeg-static 7.0.2 encodes with x264 r3191 (4613ac3); match it.
…ormat x265 now builds the 10-bit library and links it into the 8-bit one, so HDR renders get yuv420p10le instead of a silent 8-bit fallback. The check asserts the encoded pixel format rather than a successful command, and its ffprobe calls terminate options with -- like every other caller.
a51fd1d to
295c5a7
Compare
What
A pinned, reproducible build of ffmpeg + ffprobe for an arm64 Lambda video function, under
packages/aws-lambda/image/, plus a CI workflow that builds it natively on GitHub's ARM runners.Nothing ships it yet: the image and the
lambda deployoption that use it come in follow-up PRs. The default x86 ZIP deploy is untouched.Why
The x86 Lambda handler uses the
ffmpeg-staticbinary. Its arm64 sibling is a static-glibc build that crashes on Lambda during decode, and the stock dynamic arm64 builds are too large for a ZIP function. An arm64 video function therefore ships as a container image, and that image needs an ffmpeg built against the glibc of the Lambda Node 22 base it runs on, with every codec the engine calls:engine/src/services/streamingEncoder.ts(h264/h265 encode),producer/src/services/distributed/plan.ts(mp4 h265),engine/src/services/chunkEncoder.ts(HDRyuv420p10le)engine/src/services/chunkEncoder.ts(webm),parsers/src/mediaAlpha.tsalphaDecoderForengine/src/services/chunkEncoder.tsmuxVideoWithAudio(webm audio)zscale)engine/src/services/videoFrameExtractor.tstoneMapsWithZscale(assumed present on Linux),core/src/hdrToneMap.tsHow
sources.txtpins every source by sha256 (x264 by git commit, since it has no stable tarballs).Dockerfilebuilds on the Lambda Node 22 image itself (pinned by digest), so the binaries link against the exact glibc they run on. Build packages come from the base's pinned Amazon Linux 2023 release.build-ffmpeg.shlinks the codec libraries statically into a glibc-dynamic ffmpeg/ffprobe. Shared libraries the bare base lacks (GnuTLS, nettle) are copied beside the binaries and found through an$ORIGINrpath, so the runtime image needs no package install. License files and the source pins go intoshare/licenses/. The tarball is packed deterministically (sorted, fixed mtime and owner,gzip -n).check-ffmpeg.shruns in acheckstage: the bare Lambda base plus only the built tree. It asserts the encoders, decoders, filters and protocols the engine uses. It also round-trips h264, h265, ProRes 4444, Opus, AAC and PNG; checks that VP9 alpha survives encode and libvpx decode; asserts a 10-bit HEVC encode really comes outyuv420p10leand runs the engine's HDR-to-SDRzscalechain on it; and checks HTTPS against the system trust store, where a trusted host passes and a wrong host name is refused. Theartifactstage copies the check's summary, so no tarball can come out of a build whose check failed..github/workflows/lambda-ffmpeg.ymlbuilds on two separateubuntu-24.04-armrunners and fails unless both tarballs are byte-identical. It runs on PRs that touch the recipe, and by hand.Test plan
--no-cacheproduced a byte-identical tarballlibgnutls.so.30removed (ffmpeg cannot load), the wrong-host probe pointed at the right host ("accepted a wrong host"), and an earlier 8-bit-only x265 build (ffprobe reportsyuv420pfor ayuv420p10leencode)Lambda arm64 ffmpegworkflow (two native ARM builds, check stage, byte-identical comparison) passed at f43fc69; rerunning at this headNot exercised here: running these binaries inside Lambda itself. That is proven with the image and deploy PRs that use them.