Version: hyperframes 0.7.31 · Node 22.15 · Linux (WSL2)
Summary
The timing compiler scans the raw composition text for media tags with regexes that don't exclude comments. A JS/HTML comment that merely mentions <video> or <audio> (e.g. documentation prose) is treated as a real untimed media element: the compiler injects id/data-start="0"/data-hf-auto-start into the comment text, and the render pipeline then launches a browser probe on every render because runProbeStage's check is a substring match over the final HTML (compiled.html.includes("data-hf-auto-start")).
Minimal repro
A composition with no media at all, just a comment that mentions a tag:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=640, height=360" />
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<style>
body { margin: 0; background: #000; }
#root { position: relative; width: 640px; height: 360px; overflow: hidden; }
.clip { position: absolute; inset: 0; display: grid; place-items: center; }
h1 { color: #fff; font-family: sans-serif; }
</style>
</head>
<body>
<div id="root" data-composition-id="main" data-start="0" data-width="640" data-height="360" data-duration="2">
<section id="card" class="clip" data-start="0" data-duration="2" data-track-index="1"><h1 id="t">No media here</h1></section>
</div>
<script>
// This composition contains no media at all. But this comment
// mentions a <video> tag — and that is enough to trigger the bug.
window.__timelines = window.__timelines || {};
const tl = gsap.timeline({ paused: true });
tl.from("#t", { opacity: 0, duration: 0.5 }, 0.2);
window.__timelines["main"] = tl;
</script>
</body>
</html>
npx hyperframes render on this project produces:
- The comment is rewritten in the compiled/served page:
// mentions a <video id="hf-video-0" data-start="0" data-hf-auto-start="" data-has-audio="true"> tag — and that is enough…
- Compile metadata correctly says
videoCount: 0, audioCount: 0 — yet the probe launches anyway, with an empty reasons list (auto-start isn't reported as a reason):
[INFO] Compiled composition metadata {... "videoCount":0,"audioCount":0 ...}
[INFO] Launching browser for composition probe... {"reasons":[]}
Impact
- Every render of an affected composition pays an unnecessary browser launch. In our (admittedly hostile) WSL environment the probe session reliably burned the full 45s
playerReadyTimeout per render and was also the source of intermittent Network.enable timed out failures — we spent days retrying around a probe that should never have run. Removing the tag syntax from one comment took a 10s-segment draft from 63s to 19s.
- The composition's comment text is silently corrupted in the served page (confusing when debugging the compiled output).
- Because the probe's
reasons array doesn't include the auto-start condition, the launch looks completely unexplained in logs, which makes this painful to diagnose.
Where it lives (dist/cli.js, 0.7.31)
compileTag / injectAttr in ../core/dist/compiler/timingCompiler.js — the tag regex matches inside comments; when the phantom "tag" lacks data-start, data-hf-auto-start is injected.
runProbeStage: const hasAutoStartVideos = compiled.html.includes("data-hf-auto-start") — a substring match over the whole document, so any occurrence of that string (mutated comments, or even user text mentioning the attribute) forces needsBrowser.
Suggested fixes
- Strip/mask comments (and ideally string literals) before the media-tag scan, or use a real HTML parser for tag discovery.
- Track auto-start media as compile metadata (a count/list alongside
videoCount) instead of substring-matching the final HTML.
- Add the auto-start condition to the probe's
reasons array so the launch is at least explainable from logs.
Happy to provide more logs or test a patch.
Version: hyperframes 0.7.31 · Node 22.15 · Linux (WSL2)
Summary
The timing compiler scans the raw composition text for media tags with regexes that don't exclude comments. A JS/HTML comment that merely mentions
<video>or<audio>(e.g. documentation prose) is treated as a real untimed media element: the compiler injectsid/data-start="0"/data-hf-auto-startinto the comment text, and the render pipeline then launches a browser probe on every render becauserunProbeStage's check is a substring match over the final HTML (compiled.html.includes("data-hf-auto-start")).Minimal repro
A composition with no media at all, just a comment that mentions a tag:
npx hyperframes renderon this project produces:videoCount: 0, audioCount: 0— yet the probe launches anyway, with an empty reasons list (auto-start isn't reported as a reason):Impact
playerReadyTimeoutper render and was also the source of intermittentNetwork.enable timed outfailures — we spent days retrying around a probe that should never have run. Removing the tag syntax from one comment took a 10s-segment draft from 63s to 19s.reasonsarray doesn't include the auto-start condition, the launch looks completely unexplained in logs, which makes this painful to diagnose.Where it lives (dist/cli.js, 0.7.31)
compileTag/injectAttrin../core/dist/compiler/timingCompiler.js— the tag regex matches inside comments; when the phantom "tag" lacksdata-start,data-hf-auto-startis injected.runProbeStage:const hasAutoStartVideos = compiled.html.includes("data-hf-auto-start")— a substring match over the whole document, so any occurrence of that string (mutated comments, or even user text mentioning the attribute) forcesneedsBrowser.Suggested fixes
videoCount) instead of substring-matching the final HTML.reasonsarray so the launch is at least explainable from logs.Happy to provide more logs or test a patch.