Skip to content

chore(tests): move gen-os-static asset links to static.heygen.ai - #7536

Merged
miguel-heygen merged 2 commits into
mainfrom
chore/move-gen-os-static-links
Nov 12, 2026
Merged

miguel-heygen merged 2 commits into
mainfrom
chore/move-gen-os-static-links

Conversation

@sudo-rm-rf-root

@sudo-rm-rf-root sudo-rm-rf-root commented Nov 11, 2026 •

Copy link
Copy Markdown
Collaborator

About the big diff (+130 / −24,846). This PR edits 21 output/compiled.html goldens. 18 of them were stored as plain git files on main, even though .gitattributes already routes packages/producer/tests/**/output/compiled.html to Git LFS. Git applies that rule when a file is edited, so those 18 files are now LFS pointers, and the diff shows their old text as deleted. The other 3 goldens were already in LFS. Inside every file, the only change is the host name (see section 2). scripts/check-large-files.sh passes.

Why

The gen-os-static S3 bucket stops serving public reads on Fri Nov 20. After that, every link to https://gen-os-static.s3.us-east-2.amazonaws.com/... returns 403. The producer regression fixtures and the kinetic-type registry example load test videos and AI voice files from that bucket, so those tests would break.

What changed

  • The same objects, with the same keys and the same bytes, are now served from https://static.heygen.ai/<key>.
  • This PR swaps the host for all 40 keys the repo uses: 23 test videos (astral_assets/uploaded_assets/) and 17 voice files (astral_assets/generated_assets/). In total, 126 links change across 53 files.
  • The swap is made in the fixture inputs (src/index.html, src/compositions/*.html) and in the output/compiled.html goldens, so inputs and goldens stay in step.
  • Fixtures touched: style-1-prod … style-18-prod (there is no style-14-prod), dogs-captions, many-cuts, chat, font-variant-numeric, overlay-montage-prod, pip-video-late-host, sub-composition-video, vignelli-stacking, plus registry/examples/kinetic-type.
  • Not changed: the two font URLs in packages/engine/src/utils/urlDownloader.test.ts and packages/producer/src/services/htmlCompiler.test.ts. They are example strings for URL checks and are never fetched.

Evidence

1. Same files on both hosts

For each of the 40 keys, I downloaded the file in full (read-only GET) from the old URL and from the new URL. Then I compared the HTTP status, the byte count and the SHA-256.

Result: 40 of 40 match. Both hosts return 200, with the same byte count and the same SHA-256 (263 MB in total). There are no mismatches.

Table: 40 keys
Key Bytes SHA-256 (first 16) Old host New host Match
generated_assets/02937d93_65b31a3a3d1f4568b0516b66343245d6.mp3 48,736 95e015872dff3c68 200 200 yes
generated_assets/051b5d38_af2426f283a749de94ab615d459a565d.mp3 17,180 a5b8d95a914e4359 200 200 yes
generated_assets/3a7e8a33_f7ebce6d456345779477498996aa0f74.mp3 17,180 225aaf66a945e1d2 200 200 yes
generated_assets/3af40f3b_386326216dcf4956984e4c1c25663cdd.mp3 17,180 8f0e6f172ddb693d 200 200 yes
generated_assets/4ea1246d_d3e9e87e46be4104817dcd75d0adcef0.mp3 17,180 61723769fe95cb18 200 200 yes
generated_assets/52be8a19_b6ad2cf680444264933b185ff8295074.mp3 16,971 56614cbaf8504286 200 200 yes
generated_assets/52dc4e22_72f17e2dfc9f40c08f4a5cc82f53db61.mp3 17,180 1e94795bb3c7fc2d 200 200 yes
generated_assets/5a6b802e_a03d12a382bd40a3a6e70de32fbbcfc3.mp3 17,180 4391daf9141264e6 200 200 yes
generated_assets/61ada7ed_142d9432f783410185afebd0d00f1b7a.mp3 17,180 daec04a14e4d33be 200 200 yes
generated_assets/70b67ff2_d2b6d384b6124d01ba8d826bb8c1b43f.mp3 33,062 19ec08b754336eba 200 200 yes
generated_assets/731894a4_d2374e83720e4b339b6b71ceec1337d7.mp3 17,180 e4eeba8fe041bdb5 200 200 yes
generated_assets/7ae8806d_d8eacbb4b2ab4a77af89be7208c0c918.mp3 17,180 6e78741b65467b05 200 200 yes
generated_assets/853dda23_70261e8b676444bfbfe147e34803851e.mp3 17,180 76adefaf733dd9ce 200 200 yes
generated_assets/9e9b7f8a_b36aec8bcce6491f8da430e7e189f1a5.mp3 17,180 03b67017fd5b72c5 200 200 yes
generated_assets/a5bd8b8b_86b432b7de4c4fa6937b6a9cd37c67db.mp3 17,180 7dd1001b75703dbe 200 200 yes
generated_assets/bd3cb328_5d3f0ddf41c14bb8bfad8ae242024334.mp3 17,180 5272a8cc04891b0f 200 200 yes
generated_assets/f87f97d4_0c49f6fa95224cc3bd4f5ea3a0d937c5.wav 2,646,078 266ff7d5a49da0e1 200 200 yes
uploaded_assets/008477bc_391124feb22641f19fd463e5aeb1aeef.mp4 10,594,931 8ad2f37a89b4b143 200 200 yes
uploaded_assets/12ca139c_8bf35a3b61b84ab69251ad5091e4c69b.mp4 11,695,148 560fb65860d7f439 200 200 yes
uploaded_assets/1dd17e4d_2c60a8b3482744e29584975d2b84164a.mp4 12,234,008 4dbb01f3757780fb 200 200 yes
uploaded_assets/2111e840_0579531a2ffe4c3ea8295b42051fb394.mp4 10,594,931 8ad2f37a89b4b143 200 200 yes
uploaded_assets/3053bdbd_3b610ff665ee4d11858cba59dbf47b8c.mp4 10,594,931 8ad2f37a89b4b143 200 200 yes
uploaded_assets/45a6a87b_ccb8e5b8362f48129491b55141ca3cb3.mp4 10,594,931 8ad2f37a89b4b143 200 200 yes
uploaded_assets/57704cd3_8424a748578a497084fd1278949184fc.mp4 10,594,931 8ad2f37a89b4b143 200 200 yes
uploaded_assets/61ae9527_715ce519da784c0daae4f3aade82ee56.mp4 12,234,008 4dbb01f3757780fb 200 200 yes
uploaded_assets/64b11740_ce531703293e4dbfa1de029a692e93e4.mp4 12,234,008 4dbb01f3757780fb 200 200 yes
uploaded_assets/67cf5a05_e134ec83a57042b38776c952da595870.mp4 9,671,596 7a1943dcffd08baa 200 200 yes
uploaded_assets/70648f53_abe84fb9991841ae8ba82ee21ba6d37e.mp4 10,594,931 8ad2f37a89b4b143 200 200 yes
uploaded_assets/743011f1_e3c6afe3b7aa42369ce01e4961c60e22.mp4 10,594,931 8ad2f37a89b4b143 200 200 yes
uploaded_assets/852b4a6c_22c6186c3b844db1955bc9aaee70d348.mp4 10,594,931 8ad2f37a89b4b143 200 200 yes
uploaded_assets/8eb26801_b5ca4d50bb91437dac375c58b86d005c.mp4 10,594,931 8ad2f37a89b4b143 200 200 yes
uploaded_assets/a8bed725_8ae955c61e3141e09d9eadb97e0eef93.mp4 12,234,008 4dbb01f3757780fb 200 200 yes
uploaded_assets/c10d5d5c_5e0cbe68f361481f8d2c77b028e84504.mp4 12,234,008 4dbb01f3757780fb 200 200 yes
uploaded_assets/c311bdbf_97f959ca3be34382be873d54a405711b.mp4 10,594,931 8ad2f37a89b4b143 200 200 yes
uploaded_assets/cd544f35_70b817304d84455490962587aa52c167.mp4 37,433,914 1cb16830bbf25eb1 200 200 yes
uploaded_assets/e5d69fa9_6c6509753f4643cd9bef0b1dc9e1e001.mp4 10,594,931 8ad2f37a89b4b143 200 200 yes
uploaded_assets/f140a7f9_c8ae0ae2698f4a6895110bb9cbaadd74.mp4 2,203,966 2adf0f711e1acb8c 200 200 yes
uploaded_assets/f82d6e98_9076b56b449e44ac95a2099375863f91.mp4 12,234,008 4dbb01f3757780fb 200 200 yes
uploaded_assets/fb7e48ac_f6bf2ab079394d7ebd0491e7008a9242.mp4 9,423,755 5f1979d9de5c98fc 200 200 yes
uploaded_assets/fba9969d_c8c30a7e22ac40029c24c5135d27df04.mp4 12,234,008 4dbb01f3757780fb 200 200 yes

2. Only the host changed

For each of the 53 files, I compared the PR version with main (merge base eb90921). For LFS files, I compared the real content, not the pointer. Then I replaced https://gen-os-static.s3.us-east-2.amazonaws.com/ with https://static.heygen.ai/ in the main version and diffed again.

Result: 0 other changed lines in all 53 files. The table shows how many links changed in each file.

Table: 53 files
File Storage (main → PR) Links changed Other changed lines
tests/chat/output/compiled.html git → LFS 1 0
tests/chat/src/index.html git → git 1 0
tests/dogs-captions/output/compiled.html git → LFS 1 0
tests/dogs-captions/src/index.html git → git 1 0
tests/font-variant-numeric/output/compiled.html git → LFS 1 0
tests/font-variant-numeric/src/index.html git → git 1 0
tests/many-cuts/output/compiled.html git → LFS 14 0
tests/many-cuts/src/index.html git → git 14 0
tests/overlay-montage-prod/output/compiled.html git → LFS 1 0
tests/overlay-montage-prod/src/index.html git → git 1 0
tests/pip-video-late-host/output/compiled.html git → LFS 1 0
tests/pip-video-late-host/src/compositions/pip.html git → git 1 0
tests/style-1-prod/output/compiled.html git → LFS 2 0
tests/style-1-prod/src/index.html git → git 2 0
tests/style-10-prod/output/compiled.html LFS → LFS 9 0
tests/style-10-prod/src/compositions/graphics.html git → git 4 0
tests/style-10-prod/src/compositions/main-orchestration.html git → git 5 0
tests/style-11-prod/src/index.html git → git 1 0
tests/style-12-prod/output/compiled.html git → LFS 1 0
tests/style-12-prod/src/index.html git → git 1 0
tests/style-13-prod/output/compiled.html git → LFS 1 0
tests/style-13-prod/src/index.html git → git 1 0
tests/style-15-prod/output/compiled.html git → LFS 1 0
tests/style-15-prod/src/compositions/aroll.html git → git 1 0
tests/style-16-prod/output/compiled.html git → LFS 1 0
tests/style-16-prod/src/index.html git → git 1 0
tests/style-17-prod/output/compiled.html git → LFS 1 0
tests/style-17-prod/src/index.html git → git 1 0
tests/style-18-prod/output/compiled.html git → LFS 1 0
tests/style-18-prod/src/index.html git → git 1 0
tests/style-2-prod/src/compositions/intro.html git → git 1 0
tests/style-2-prod/src/compositions/stats.html git → git 3 0
tests/style-2-prod/src/index.html git → git 1 0
tests/style-3-prod/output/compiled.html git → LFS 5 0
tests/style-3-prod/src/index.html git → git 5 0
tests/style-4-prod/src/index.html git → git 4 0
tests/style-5-prod/output/compiled.html git → LFS 1 0
tests/style-5-prod/src/compositions/main.html git → git 1 0
tests/style-5-prod/src/index.html git → git 1 0
tests/style-6-prod/output/compiled.html git → LFS 2 0
tests/style-6-prod/src/index.html git → git 2 0
tests/style-7-prod/src/compositions/main.html git → git 1 0
tests/style-7-prod/src/index.html git → git 1 0
tests/style-8-prod/output/compiled.html git → LFS 1 0
tests/style-8-prod/src/compositions/main-video.html git → git 1 0
tests/style-9-prod/output/compiled.html git → LFS 8 0
tests/style-9-prod/src/index.html git → git 8 0
tests/sub-composition-video/output/compiled.html LFS → LFS 2 0
tests/sub-composition-video/src/compositions/polaroid.html git → git 1 0
tests/sub-composition-video/src/index.html git → git 1 0
tests/vignelli-stacking/output/compiled.html LFS → LFS 1 0
tests/vignelli-stacking/src/index.html git → git 1 0
registry/examples/kinetic-type/index.html git → git 1 0

3. The tests render

CI. The regression workflow runs these fixtures in Docker, split into shards. On this PR's head (a606c6e), run 42955167571 passed all 10 shards. It covered 24 of the 25 changed fixtures, and every one passed. The shard logs show 78 downloads from static.heygen.ai, all with status 200 and the full byte count. No asset was downloaded from gen-os-static. (A later run on the same commit skipped the shards because that commit had already passed.)

Table: CI result per fixture
Fixture CI shard (mode) Result
chat shard-7 (in-process) pass
font-variant-numeric shard-3 (in-process) pass
many-cuts shard-6 (in-process) pass
overlay-montage-prod shard-3 (in-process) pass
pip-video-late-host shard-4 (in-process) pass
style-1-prod shard-9 (in-process) pass
style-2-prod shard-7 (in-process) pass
style-3-prod shard-5 (in-process) pass
style-4-prod shard-2 (in-process) pass
style-5-prod shard-5 (in-process) pass
style-6-prod shard-1 (in-process) pass
style-7-prod shard-9 (in-process) pass
style-8-prod shard-8 (in-process) pass
style-9-prod shard-2 (in-process) pass
style-10-prod shard-5 (in-process) pass
style-11-prod shard-1 (in-process) pass
style-12-prod shard-4 (in-process) pass
style-13-prod shard-4 (in-process) pass
style-15-prod shard-10 (distributed-simulated) pass
style-16-prod shard-9 (in-process) pass
style-17-prod shard-3 (in-process) pass
style-18-prod shard-6 (in-process) pass
sub-composition-video shard-10 (distributed-simulated) pass
vignelli-stacking shard-1 (in-process) pass

dogs-captions runs nightly only (shard-schedule.json: one long fixture, 7 to 10.5 min), so CI did not run it on this PR. No CI job renders registry/examples/kinetic-type.

Local, on a Mac (arm64), --mode=in-process. Docker was not available, so I could not use the CI image. To separate the link change from differences in this Mac's setup, I ran each fixture twice: once with the PR version, and once with main's version of the same fixture.

Fixture PR (fetches static.heygen.ai) main (fetches gen-os-static) Same render?
dogs-captions pass: compile, visual (0 failed frames, min PSNR 31.80), audio (corr 0.962) pass, same numbers yes: identical PSNR at all 100 checkpoints
overlay-montage-prod pass: compile, visual (0 failed frames, min PSNR 31.76), audio (corr 0.954) pass yes, within noise: 11 of 100 checkpoints differ by ≤ 0.02 dB
style-1-prod compile pass, audio pass, visual fail (25 frames below the PSNR limit) the same failure yes: identical PSNR at all 100 checkpoints
style-2-prod compile fail: audio data-end / data-duration off by about 40 ms from the golden the same failure yes: the same errors
kinetic-type (hyperframes render -q draft) renders: 15.0 s, 1920×1080, with audio renders yes: the two MP4s are byte-identical (same SHA-256)

The style-1-prod and style-2-prod failures happen on main too, so the link change does not cause them. They likely come from this Mac's Chrome and ffmpeg/ffprobe (7.1.5), which differ from the CI image. Both fixtures pass in CI on this PR.

Other checks: bun run lint passes, and oxfmt --check on the edited source HTML passes. bun run build, the producer unit tests (86 files, 1,290 tests) and the producer typecheck pass. Some engine unit tests about ffmpeg colour and frame sampling fail locally, for the same local-ffmpeg reason. This PR changes no engine file.

4. What I could not test

  • The CI Docker image, locally. Docker was not running on this machine, so my local renders used this Mac's Chrome and ffmpeg. The CI run above is the real check for the 24 fixtures it covers.
  • dogs-captions in CI. It runs only in the nightly regression job. I rendered it locally only: it passed, with the same output as main.
  • kinetic-type in CI. No CI job renders registry examples. I rendered it locally only: the output is byte-identical to main's.
  • The fixtures I did not render locally (the other 20 changed fixtures). These rely on the CI run, plus sections 1 and 2: identical bytes behind each link, and no change other than the host.

🤖 Generated with Claude Code

sudo-rm-rf-root and others added 2 commits November 10, 2026 22:32
The gen-os-static S3 bucket stops serving public reads on Nov 20. The
producer regression fixtures and the kinetic-type example load test
videos and voice files from it.

The same objects, with the same keys and the same bytes, are now served
from https://static.heygen.ai/<key>. This swaps the host for 39 of the
40 keys, in the fixture inputs and in the compiled.html goldens, so they
stay in step.

The dogs-captions clip (uploaded_assets/12ca139c_...mp4) stays on the
old host for now. It is held until we decide to copy it or replace it.

17 compiled.html goldens were stored as plain git blobs although
.gitattributes routes them to LFS. Editing them moves them into LFS.

The two font URLs in urlDownloader.test.ts and htmlCompiler.test.ts are
unchanged. They are example strings and are never fetched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dogs-captions clip (uploaded_assets/12ca139c_...mp4) is now copied
to static.heygen.ai with the same bytes. This swaps its host in the
fixture input and in the compiled.html golden, which moves into LFS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sudo-rm-rf-root
sudo-rm-rf-root marked this pull request as ready for review November 12, 2026 23:14

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review at a606c6e31. There were no other reviews when I posted.

Verified

  • No fetched old-host URL is left.
    • git grep gen-os-static at the head finds only the two font strings.
    • I fetched and smudged all 50 LFS-tracked .html files at the head. None of them mention the old host.
    • The two font strings are never fetched. htmlCompiler.test.ts:2272 goes through stubDownloadFetch.fetch, which the test stubs. urlDownloader.test.ts:170 only goes through assertPublicHttpsUrl.
  • All 40 keys are byte-identical on both hosts.
    • Every key returns 200 from static.heygen.ai (CloudFront in front of S3). Its Content-Length and ETag match the old bucket, including the multipart ETags on the large videos.
    • I also downloaded one key from both hosts (f140a7f9…mp4), and the md5 sums match.
  • Inputs and goldens change in step.
    • I smudged base and head for all 53 changed files and swapped gen-os-static.s3.us-east-2.amazonaws.com/ for static.heygen.ai/ in the base copy.
    • All 53 are then byte-identical to the head, so no golden changes beyond the host. That covers the 18 goldens that move from blob to LFS and the 3 that were already in LFS.
  • LFS routing works, and CI used real golden content.
    • .gitattributes:18 routes packages/producer/tests/**/output/compiled.html to LFS. regression.yml:122 checks out with lfs: true.
    • In the shard logs, every touched fixture reports compilation_complete with errors:0, warnings:0. A golden left as a bare pointer would have no timed elements, so the comparison would have logged "Extra element" warnings for it. That confirms the comparison ran against real LFS content.
  • CI. All regression shards and every other check are green on this head.
  • dogs-captions. It is tagged slow, so only the daily full run renders it. Its change is covered by the content check and the byte check above.

Nit (non-blocking): four goldens keep hashes of the old URLs

  • style-2-prod, style-4-prod, style-7-prod and style-11-prod changed their sources but not their output/compiled.html goldens.
  • Those goldens don't contain the URL. They contain _remote_media/download_<md5(url)[0:12]>, from getFilenameFromUrl at urlDownloader.ts:228-233, and six of those names are hashes of the old URLs. For example, style-4-prod has download_1994e3d3b268, while the new URL gives download_47352078640b.
  • So a fresh compile now produces different filenames from those goldens.
  • CI doesn't notice because validateCompilation (compilationTester.ts:231) compares only data-composition-src, not media src.
  • Nothing breaks. But the body's "inputs and goldens stay in step" isn't quite true for these four, and the next --update will churn them.
  • Regenerating those four with --update, or replacing the six hashes by hand, would close it.

Verdict: APPROVE
Reasoning: Every fetched link now points at a host that serves the same bytes, the goldens differ only by the host swap, and the LFS-backed regression run is green on this exact head. The stale download hashes in four goldens are cosmetic.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Nov 12, 2026
Merged via the queue into main with commit aadd5bd Nov 12, 2026
170 of 171 checks passed
@miguel-heygen
miguel-heygen deleted the chore/move-gen-os-static-links branch November 12, 2026 23:44
@miguel-heygen miguel-heygen mentioned this pull request Nov 13, 2026
3 of 5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants