You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The <video muted> + <audio> two-element pattern documented in skills/hyperframes/SKILL.md §"Video and Audio" — with the same src on both elements — produces a runtime StaticGuard contract violation when followed verbatim.
The compiler unconditionally injects data-has-audio="true" on every <video> without an explicit attribute (packages/core/src/compiler/timingCompiler.ts:104-106), regardless of whether the video file actually contains an audio stream. Combined with muted, this trips the StaticGuard rule at packages/core/src/lint/rules/media.ts:274 ("declares data-has-audio="true" but also has muted").
The lint rule duplicate_audio_track added in #299 only checks <audio>–<audio> overlaps, so it does not catch this case where a <video> and an <audio> reference the same src on a muxed file.
This matters because the SKILL.md canonical example uses identical src="video.mp4" on both elements — an agent that follows the skill canon literally will scaffold a project that fails its own validate.
Clean validation — no contract warning. The canonical example of the canonical pattern should not be flagged invalid by the canonical lint.
Actual behavior
◆ Validating my-video in headless Chrome
[StaticGuard] Invalid HyperFrame contract: <video id="el-v"> declares data-has-audio="true" but also has muted. Studio preview will silence the video audio.
◇ No console errors
In a real composition that uses this scaffold (talking-head muxed final.mp4), the studio preview also produces audible distortion. The capture engine output is clean (consistent with #298's "capture bypasses both DOM pipelines and muxes audio from source files" note).
Verified workarounds
Adding explicit data-has-audio="false" to the <video> element silences StaticGuard. Compiler skips auto-injection when the attribute is already present (!hasAttr(result, "data-has-audio") guard), and audioMixer's strict equality on "true" excludes this <video> from the mix. The two-element pattern then works as intended.
Stripping the audio stream from the video file (ffmpeg -an) does not help — the compiler still injects data-has-audio="true" because it does not probe the file.
Suggested fixes (any one is sufficient)
Doc fix (cheap): update skills/hyperframes/SKILL.md §"Video and Audio" to include data-has-audio="false" on the <video> when both elements share src. Also surface the attribute in the All-Clips table — it is currently documented only in packages/cli/src/docs/data-attributes.md, which is not part of the agent-facing skill canon.
Describe the bug
The
<video muted>+<audio>two-element pattern documented inskills/hyperframes/SKILL.md§"Video and Audio" — with the samesrcon both elements — produces a runtimeStaticGuardcontract violation when followed verbatim.The compiler unconditionally injects
data-has-audio="true"on every<video>without an explicit attribute (packages/core/src/compiler/timingCompiler.ts:104-106), regardless of whether the video file actually contains an audio stream. Combined withmuted, this trips the StaticGuard rule atpackages/core/src/lint/rules/media.ts:274("declares data-has-audio="true" but also has muted").The lint rule
duplicate_audio_trackadded in #299 only checks<audio>–<audio>overlaps, so it does not catch this case where a<video>and an<audio>reference the samesrcon a muxed file.This matters because the SKILL.md canonical example uses identical
src="video.mp4"on both elements — an agent that follows the skill canon literally will scaffold a project that fails its own validate.Link to reproduction
https://github.com/sidorovanthon/hyperframes-repro-double-audio-same-src
Steps to reproduce
npm installnpx hyperframes validateExpected behavior
Clean validation — no contract warning. The canonical example of the canonical pattern should not be flagged invalid by the canonical lint.
Actual behavior
In a real composition that uses this scaffold (talking-head muxed
final.mp4), the studio preview also produces audible distortion. The capture engine output is clean (consistent with #298's "capture bypasses both DOM pipelines and muxes audio from source files" note).Verified workarounds
data-has-audio="false"to the<video>element silences StaticGuard. Compiler skips auto-injection when the attribute is already present (!hasAttr(result, "data-has-audio")guard), andaudioMixer's strict equality on"true"excludes this<video>from the mix. The two-element pattern then works as intended.ffmpeg -an) does not help — the compiler still injectsdata-has-audio="true"because it does not probe the file.Suggested fixes (any one is sufficient)
skills/hyperframes/SKILL.md§"Video and Audio" to includedata-has-audio="false"on the<video>when both elements sharesrc. Also surface the attribute in the All-Clips table — it is currently documented only inpackages/cli/src/docs/data-attributes.md, which is not part of the agent-facing skill canon.duplicate_audio_track(fix: double-audio scaffold, lint rules, docs guide, Gemini 3.1 #299) to also flag a<video src=X muted>+<audio src=X>pair overlapping in time — functionally a duplicate audio track from the same muxed source.data-has-audioauto-injection conditional — skip on<video muted>, or probe the source for an audio stream before injecting.Environment
hyperframes0.4.41 (latest stable; fix(player): single-owner audio to prevent double voice in preview #298 and fix: double-audio scaffold, lint rules, docs guide, Gemini 3.1 #299 included)