Remotion Lambda Chrome 二进制发布流程:test 区域验证、托管 Layer 同步与全量发布前的把关
本文基于 Remotion 仓库中的 Agent Skill 文档 update-chrome-binaries-test-region/SKILL.md,完整还原了 Remotion Lambda 在升级 Chromium 二进制时的标准操作流程:先在 eu-central-1 测试区域发布 5 个托管 Layer,同步 hosted-layers.ts 与仓库内 5 处 Chrome 版本引用,再用 dockerfiles 测试矩阵 对新二进制做端到端验证。读完后,你将掌握一次完整的“test 区域 → 全区域”Chrome 升级操作链,以及每一步在源码中的对应实现。
一、流程总览:为什么先有 test 区域
Remotion Lambda 把渲染所需的 Chromium、字体等二进制以 AWS Lambda Layer 形式托管在自有 AWS 账号 678892195805 下。每次 Chromium 大版本升级不能直接推到所有区域,标准做法是:
- AWS setup:把 5 个 Layer 发布到
eu-central-1测试区域; - Update hosted layers:把发布脚本输出的 ARN/版本写回
hosted-layers.ts; - Update Chrome references:同步仓库中 5 处 Chrome 版本引用(下载 URL、License 字符串、3 篇文档);
- Docker verification:在本地 Docker 矩阵中用新二进制真实渲染两个测试视频;
- 测试区域端到端验证通过之前,不允许继续向所有区域发布。
二、AWS setup:凭证准备与发布命令
2.1 登录与凭证导出
- 运行
aws sts get-caller-identity,确认当前 AWS CLI 已登录到账号678892195805;如果不是,需要先让操作者登录。 - 运行
eval "$(aws configure export-credentials --format env)"把凭证导出到 shell 环境变量。原因很具体:Lambda client 检查的是AWS_ACCESS_KEY_ID环境变量,它不会自己拾取 SSO 或 Identity Center 的凭证。 - 关键的运维细节:
eval与后面执行bun的发布命令必须在同一次 shell 调用中完成,因为环境变量不会跨 shell 调用持久化。
2.2 发布命令
在 packages/lambda 目录下运行:
bun src/admin/make-layer-public.ts --region=eu-central-1
该命令会一次性发布全部 5 个 Layer:fonts、chromium、emoji-apple、emoji-google、cjk。
执行成功的判据:标准输出中为 5 个 Layer 各自打印出 LayerArn 和 Version,最后还有一段完整的 JSON dump,其中已填充刚发布的区域条目。
2.3 源码解析:make-layer-public.ts 做了什么
make-layer-public.ts 的实现与文档完全对应:
- 区域参数解析:
parseRegionFlag()支持--region=eu-central-1与--region eu-central-1两种写法;指定--region时只处理该单个区域(并打印Filtering to region: ...)。parseSkipFlag()支持--skip=region1,region2,被跳过的区域保持旧版本不动——这正是“测试阶段只动eu-central-1”的底层保障。 - 区域白名单:
layerInfo是一个覆盖 24 个区域的HostedLayers结构,不在白名单中的区域会直接抛出Remotion-hosted Layers are not supported in <region>。 - S3 来源:Layer 内容取自区域桶
remotionlambda-binaries-${region}中的remotion-layer-<layer>-v18-arm64.zip,通过getBucketName()拼接。 - 发布与开放:对每个 Layer 依次发送
PublishLayerVersionCommand(CompatibleRuntimes为nodejs24.x,Description为当前 RemotionVERSION),再发送AddLayerVersionPermissionCommand,以Principal: '*'、StatementId: 'public-layer'开放lambda:GetLayerVersion权限,使 Layer 公开可用。 - 输出:每个 Layer 打印
{LayerArn, Version},全部完成后打印空行与JSON.stringify(layerInfo, null, 2),也就是文档所说的“最终 JSON dump”。
其中 chromium Layer 的 LicenseInfo 硬编码为 Chromium 149.0.7790.0, compiled from source. ...(make-layer-public.ts#L113-L122)——这一行就是后文“更新 Chrome 引用”清单中的第 2 项。
三、Update hosted layers:把发布结果同步回代码
操作方式是复制粘贴,而不是手改:
- 从发布脚本 stdout 末尾的 JSON dump 中,找到
hosted-layers.ts对应区域条目的layerArn与version; - 直接替换 hosted-layers.ts 中对应区域的条目,不要手动递增版本号——版本号必须与 AWS 实际返回的
Version一致。
该文件导出的核心结构(hosted-layers.ts#L3-L17):
REMOTION_HOSTED_LAYER_ARN = arn:aws:lambda:*:678892195805:layer:remotion-binaries-*:用户侧用于匹配 Remotion 托管 Layer 的 ARN 通配式;HostedLayers类型按HostedLayerRegion(排除cn-north-1、cn-northwest-1)为键,每区域挂一个AwsLayer[]({layerArn, version}数组)。
从当前文件内容看,各区域的 5 个 Layer 版本号并不一致(例如 eu-central-1 的 fonts/chromium 已到 64,而多数其他区域 chromium 仍在 30 左右),这正是“测试区域先行、其他区域留在旧版本等待全量 rollout”这一策略在代码中的直接体现。测试阶段(--region=eu-central-1)只更新 eu-central-1 条目;若发布时使用了 --skip=<region>,被跳过区域的条目保持原样。
四、Update Chrome references:5 处版本引用的同步清单
升级 Chromium 时,需要先向操作者确认两个输入:新的 Chrome 版本号(如 149.0.7790.0)和对应的 Playwright revision。若操作者没有提供 Playwright revision,则需到 browsers.json(Playwright 上游的 packages/playwright-core/browsers.json)中按 browserVersion 字段匹配查出。
随后按下表更新 5 处引用:
| 文件 | 更新内容 |
|---|---|
| get-chrome-download-url.ts | TESTED_VERSION、PLAYWRIGHT_VERSION、PLAYWRIGHT_VERSION 行尾的 // <version> 注释、两条硬编码的 https://remotion.media/chromium-headless-shell-amazon-linux-{arm64,x64}-<version>.zip URL |
| make-layer-public.ts | 传给 PublishLayerVersionCommand 的 Chromium <version>, compiled from source. 许可证字符串 |
| runtime.mdx | 在“Chrome”版本表中为下一个 Remotion 版本新增一行。下一个版本号从 core/package.json 的当前版本 patch +1 得出 |
| chrome-headless-shell.mdx | 版本表新增一行,并更新“Version tracking”一节示例中的版本字符串 |
| ensure-browser.mdx | 更新示例代码块中两处 version: '<old>' |
4.1 二进制存在性校验(改 URL 之前必须做)
在改动任何下载 URL 之前,先用 curl -sI 验证新二进制确实存在:
- 两条新的硬编码
amazon-linux-{arm64,x64}URL; - 跟随
TESTED_VERSION拼接出来的两条chromium-headless-shell-linux-{arm64,x64}-<version>.zip?clearcacheURL。
只有全部返回 HTTP 200 才继续;任何一个 404 都说明新构建还没传到 remotion.media,此时应当请操作者先把缺失的构建上传,而不是继续改代码。
4.2 为什么 renderer 里有这么多分支
结合 get-chrome-download-url.ts 的源码可以看到这些 URL 的实际用途:
- 当前
TESTED_VERSION = '149.0.7790.0',PLAYWRIGHT_VERSION = '1421'(get-chrome-download-url.ts#L7-L10); remotion.media上的二进制构建于 Ubuntu 24.04,要求 glibc 2.35+(MINIMUM_GLIBC_FOR_REMOTION_MEDIA = [2, 35]);检测不到足够 glibc 时会回退到 Playwright / Chrome-for-Testing CDN 的构建;- Amazon Linux 2023 有特殊分支:
isAmazonLinux2023()通过解析/etc/os-release识别该发行版,此时返回硬编码的chromium-headless-shell-amazon-linux-{arm64,x64}-149.0.7790.0.zip——这类构建兼容更旧的 glibc,不要求 2.35。这就是文档要求这两条 URL 必须随版本同步更新的原因:它们是唯一不经过TESTED_VERSION模板拼接的下载路径。
五、Docker verification:测试区域的端到端把关
最后一步是在 packages/dockerfiles/ 目录用 ./run.sh 跑 Docker 矩阵测试,验证新 Chrome 二进制。前提:Docker Desktop 先处于运行状态。
5.1 run.sh 做了什么
run.sh 的关键步骤:
- 先在
packages/renderer构建浏览器下载器(bun build-browser-downloader.ts); - 运行
bun pack-cli.ts:Docker 镜像安装的是本地 workspace 构建的@remotion/cli及其传递依赖,而不是 npm 上已发布的版本。因此@remotion/renderer的源码改动在未发布前就会被测到——这保证了测试测的是“即将发布的代码 + 新二进制”; - 从
packages/example打 bundle:bunx remotion bundle src/browser-test-entry.ts --out-dir ../dockerfiles/bundle; - 对矩阵中每个 Dockerfile 执行
build_and_extract,docker build后用docker create+docker cp取出两个视频,最后docker rm清理容器。
pack-cli.ts 的机制:从 @remotion/cli 出发遍历所有 workspace:* 传递依赖,对每个包执行 bun pm pack 产出 tarball 到 packages/dockerfiles/tarballs/,再生成 local-cli-package.json——把每个 tarball 同时作为直接依赖和 overrides 条目写入,从而在传递解析层面强制使用本地构建而非同版本的注册表拷贝。
当前矩阵包含的平台(run.sh#L54-L64):ubuntu24-x86、ubuntu22-x86、debian-x86(通过 --platform linux/amd64 做 x86 模拟构建,便于在 ARM 机器上测试),以及 ubuntu24、ubuntu22、debian 本机构建;al2023 与 nix 目前处于注释停用状态。
5.2 两个测试 composition 与产物
渲染的产物落在 packages/dockerfiles/out/:
out/<platform>.mp4——browser-test视频:Three.js、WebGL 与编解码(codec)冒烟测试;out/<platform>-html-in-canvas.mp4——html-in-canvas视频:实验性的 WICGdrawElementImage()与canvas.requestPaint()API 验证。
两个 composition 都注册在 BrowserTestRoot.tsx:browser-test(1280x720,30fps,2 分钟)与 html-in-canvas(1920x1080,30fps,120 帧)。如果未来往矩阵中新增 composition,需要两处登记:在 BrowserTestRoot.tsx 注册 composition,并在 run.sh 中加上对应的 RUN remotion render /usr/app/bundle <id> /usr/app/<filename>.mp4 渲染行以及 docker cp 提取行。
5.3 html-in-canvas 失败时的快速定位
HtmlInCanvas.tsx 中的 isHtmlInCanvasSupported() 运行时检查要求同时存在 4 个 API:
ctx.drawElementImage(CanvasRenderingContext2D上);canvas.requestPaint;canvas.captureElementImage;canvas.transferControlToOffscreen。
这些 API 在 Chrome 149+ 传入 --enable-features=CanvasDrawElement 时暴露。据此,文档给出了一个非常实用的排障规则:如果 html-in-canvas 渲染以 "HTML in Canvas is not supported" 失败、而 browser-test 却通过,最可能的原因就是 Chrome 版本不匹配——基础浏览器功能正常,但新的 HTML-in-Canvas 实验 API 不可用,指向二进制版本或 feature flag 的问题。
六、操作要点自查清单
- [ ]
aws sts get-caller-identity确认账号为678892195805; - [ ]
eval "$(aws configure export-credentials --format env)"与bun src/admin/make-layer-public.ts --region=eu-central-1在同一次 shell 调用中执行; - [ ] stdout 中 5 个 Layer 均有
LayerArn与Version,且末尾 JSON dump 的eu-central-1条目已更新; - [ ]
hosted-layers.ts仅更新了eu-central-1(或未被--skip的区域),版本号为 AWS 返回值而非手动递增; - [ ]
curl -sI对新硬编码 URL 与模板 URL 全部返回 200 后才改动get-chrome-download-url.ts; - [ ] 5 处 Chrome 引用(renderer、lambda、3 篇文档)全部同步,
runtime.mdx新版本行对应core/package.json的 patch +1; - [ ] Docker 矩阵跑完,
out/下两类视频齐全,browser-test与html-in-canvas均正常; - [ ] 以上全部通过后,才进入向所有区域发布的阶段。
整套流程的本质是:用一个单区域小范围发布 + 本地 Docker 端到端渲染,把“新 Chromium 二进制 + 未发布 renderer 代码”的组合风险压到最小,验证通过后再全量 rollout。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00