fix(cli): resolve sub-composition <audio> src relative to its own file#489
Merged
miguel-heygen merged 1 commit intoheygen-com:mainfrom Apr 25, 2026
Merged
Conversation
`lintAudioSrcNotFound` resolves every `<audio src>` against the project root, which is correct for index.html but wrong for sub-compositions — their srcs are written relative to the sub-composition file (e.g. `../assets/foo.mp3`), and the bundler rewrites them at compile time. Carry the sub-composition path alongside each html source and run `<audio src>` strings starting with `../` through the existing `rewriteAssetPath` helper before checking existence on disk. Mirrors the runtime/bundler behaviour so the lint check sees the same path the renderer will fetch. Original (un-rewritten) src is still surfaced in the finding message so authors can grep for it in their HTML.
miguel-heygen
approved these changes
Apr 25, 2026
Collaborator
miguel-heygen
left a comment
There was a problem hiding this comment.
This fixes a real lint false positive for sub-composition audio paths. I reproduced the base behavior (../assets/bgm.mp3 was reported missing even though {project}/assets/bgm.mp3 existed), verified the head removes only that false positive while preserving the missing-file error, and checked the changed-file lint/format/unit tests plus green CI on the live head.
9 tasks
8 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
lintAudioSrcNotFoundwas reportingaudio_src_not_founderrors for<audio>elements inside sub-compositions whosesrcattribute starts with../, even when the file actually exists at the path the bundler rewrites to.Why
The pre-render lint check is currently produced by reading every HTML source (root + each
compositions/*.html) into a single string array, then for each<audio src>doingresolve(projectDir, src)and checking the filesystem. That's correct for the root index.html but wrong for sub-compositions:compositions/scene.htmlwrites<audio src="../assets/foo.mp3">because its bundler rewrites paths relative to the sub-composition's own file (seerewriteAssetPathinpackages/core/src/compiler/rewriteSubCompPaths.ts).resolve(projectDir, "../assets/foo.mp3")walks one level above the project — to{parentOfProject}/assets/foo.mp3— which does not exist, so the lint check reports the file as missing.Net effect: a project that follows the documented authoring model (sub-composition assets written relative to the sub-composition file) gets a hard
audio_src_not_founderror fromhyperframes lint, even thoughhyperframes previewandhyperframes renderboth work correctly.How
Replace the bare
string[]ofhtmlSourceswithHtmlSource[] = { html, compSrcPath? }.compSrcPathis thedata-composition-srcvalue (e.g.compositions/scene.html); the root index.html leaves itundefined.Inside
lintAudioSrcNotFound, when a sub-composition source'ssrcmatches the existing rewrite criteria, run it through the bundler's ownrewriteAssetPath(compSrcPath, src)helper to convert../assets/foo.mp3intoassets/foo.mp3. Thenresolve(projectDir, ...)against the rewritten path.Keep the original (un-rewritten)
srcin themissingSrcsarray so the finding message and fix hint remain greppable from the author's HTML — they should see what they wrote, not the rewritten internal form.Update
lintProjectAudioFilesandlintDuplicateAudioTrackssignatures to accept the sameHtmlSource[], since they read off the same array. Their internal logic doesn't depend oncompSrcPath, but the type has to match.rewriteAssetPathis already exported from@hyperframes/core(used by the producer/preview bundlers). No new dependency, no duplication of path-rewrite logic.Test plan
bunx oxlint packages/cli/src/utils/lintProject.ts packages/cli/src/utils/lintProject.test.ts— cleanbunx oxfmt --check packages/cli/src/utils/lintProject.ts packages/cli/src/utils/lintProject.test.ts— cleanbun run --filter @hyperframes/cli typecheck— cleanbunx vitest run src/utils/lintProject.test.ts(inpackages/cli) — 39 tests pass (37 previous + 2 new)lintProject.test.ts:resolves sub-composition src relative to the sub-composition file (../assets/...)— sub-comp atcompositions/captions.htmlreferencing../assets/bgm.mp3with the file present at{project}/assets/bgm.mp3→ noaudio_src_not_foundfindingflags sub-composition src that resolves to a missing file via ../— same shape but no file on disk → finding raised, message contains the original../assets/...src so authors can grep itdist/cli.jsin a real project with a sub-composition that references nine<audio>elements via../assets/narration/*.mp3. Before the patch: 9 hard errors despite all files existing andrendersucceeding. After the patch: lint clean for those audio sources. Renaming one of the mp3s on disk still produces the expected single error pointing at the un-rewritten path, so the rule still catches genuine misses.Non-goals
rewriteAssetPathas the source of truth — same behaviour, same edge cases.audio_src_not_foundfinding message format beyond what already shows up. Authors continue to see the literalsrcthey wrote.