mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 17:27:09 +00:00
* feat(cli): one owner for init media placeholders, audio stays on the video Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(cli): init keeps a video's sound on the clip; silent files scaffold muted Supersedes the patchVideoSrc changes in #3977 and #3942 and carries their tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: miga-heygen <miga-heygen@users.noreply.github.com> Co-Authored-By: kapelame <kapelame@users.noreply.github.com> * feat(registry): example templates keep the a-roll's sound on the video Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(lint): video audio rules recommend keeping sound on the video Update video_missing_muted and video_audio_double_source message and fixHint text to recommend the new default: keep audio on the video with data-has-audio="true" (not muted). Tests verify the new wording is in place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(parsers): a video is either audible (data-has-audio) or muted, never both Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(studio): follow the compiler's audio rule in the audio-track toggle Confirm before background removal drops a video's sound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(skills): hyperframes-core teaches sound on the video by default Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(skills): workflows and scaffold guidance keep a video's sound on the clip Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: footage with sound keeps it on the video clip Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): init from-file a-roll is timed, muted strip is attribute-exact The from-file a-roll video gets data-start="0" so a scaffold lints clean, and the orphaned audio-only slot comment is dropped. setVideoAudio now walks the tag attribute by attribute, so a class value containing the word muted survives. The ffprobe-missing warning says the video is assumed to have sound and how to switch to muted, and DEFAULT_META notes the failure surfaces at render until lint support lands. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(studio): keep has-audio in step with the muted toggle, test cutout confirm Muting a video now clears has-audio and unmuting sets it to true, in both the Design and flat media panels, matching the Has audio track toggle. Audio elements are unchanged. Adds coverage for both panels plus the cutout window.confirm guard: declined leaves src alone, accepted swaps src and mutes, a silent video never prompts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(parsers): updateElementInHtml hasAudio only applies to videos, true or false An audio element or an undefined hasAudio no longer picks up a muted attribute; only an explicit false on a video writes muted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: video_missing_muted rule text, silent-footage notes, consistent audible examples lint.mdx and cli.mdx describe the current video_missing_muted rule instead of the retired unmuted-video wording. The editing recipes say how to adapt for silent footage and require the outgoing clip's sound to end at a J-cut. The Remotion media example shows the audible mapping consistently, data-attributes states that has-audio is required unless muted, and the hairline frame note no longer claims the video is muted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): encode init media filenames and probe --audio duration Function replacers stop dollar-sign pattern expansion in filenames; src is percent-encoded. --audio now passes the probed track length as the composition duration in both init paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(lint): audio-state-aware media rules and time-aware double-source check video_missing_muted honors any explicit data-has-audio. video_audio_double_source only considers audible videos and only fires when the same-src clips overlap in time. duplicate_audio_track now covers audible videos. audio_file_without_element no longer claims silence when an audible video carries the sound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(skills): audio-stream check for remotion ports, followable J-cut recipe Remotion Video maps to data-has-audio only when the file has an audio stream. The J/L-cut recipe now shows both shots with muted pictures and separate audio. embedded-captions removes the audio.mp3 scratch file it extracts. skills-manifest.json regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(lint): trim comments to satisfy the comment ratchet Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(studio): atomic muted edits, cutout keeps sound on a linked audio Muted and Has audio track commit one batched write (one persist, one undo entry) and remove data-has-audio instead of writing an empty marker. Unmuting a video probes its src: audible -> true, silent -> false, probe failed -> absent. Remove background on an audible video inserts a linked sibling <audio> with the original sound in the same write, replacing the drop-the-sound confirm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(producer): skip hidden videos when auto-adding video audio A video hidden in Studio is dropped by the mixer, so its src never reached existingAudioSrcs and the render re-added it at full volume. The video parser now records the shared hidden predicate and the auto-detect step skips hidden videos. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(studio): keep useDomEditSession under the 600-line cap Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: miga-heygen <miga-heygen@users.noreply.github.com> Co-authored-by: kapelame <kapelame@users.noreply.github.com>
191 lines
6.8 KiB
HTML
191 lines
6.8 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<!--
|
|
REQUIRED: viewport must match your composition dimensions.
|
|
Landscape: width=1920, height=1080
|
|
Portrait: width=1080, height=1920
|
|
-->
|
|
<meta name="viewport" content="width=1920, height=1080" />
|
|
|
|
<!--
|
|
REQUIRED: data-composition-id identifies this composition.
|
|
Must match the key you register in window.__timelines below.
|
|
Optional: data-width/data-height help the producer determine resolution.
|
|
-->
|
|
<meta data-composition-id="my-video" data-width="1920" data-height="1080" />
|
|
|
|
<title>My Video</title>
|
|
|
|
<!-- REQUIRED: GSAP for timeline animations -->
|
|
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
|
|
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
html,
|
|
body {
|
|
width: 1920px;
|
|
height: 1080px;
|
|
overflow: hidden;
|
|
background: #000;
|
|
}
|
|
|
|
#stage {
|
|
position: relative;
|
|
width: 1920px;
|
|
height: 1080px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/*
|
|
REQUIRED: All timed clips need visibility: hidden.
|
|
The framework toggles visibility based on data-start/data-duration.
|
|
Never toggle visibility yourself in scripts.
|
|
*/
|
|
.clip {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
visibility: hidden;
|
|
object-fit: cover;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="stage">
|
|
<!--
|
|
════════════════════════════════════════════════════
|
|
VIDEO CLIPS
|
|
════════════════════════════════════════════════════
|
|
|
|
REQUIRED attributes:
|
|
data-start — when the clip appears (seconds)
|
|
data-duration — how long the clip stays on screen (seconds)
|
|
(optional for video/audio — defaults to source duration)
|
|
data-track-index — z-stacking order + timeline track grouping
|
|
(higher = in front, clips on same track cannot overlap)
|
|
|
|
REQUIRED on <video>:
|
|
data-has-audio="true" — keep the clip's own sound (no muted); silent footage: muted
|
|
playsinline — prevents fullscreen on mobile
|
|
|
|
REQUIRED:
|
|
class="clip" — sets visibility: hidden so framework can manage lifecycle
|
|
|
|
DO NOT:
|
|
- Call video.play(), video.pause(), or set video.currentTime in scripts
|
|
- Toggle visibility in scripts
|
|
- Add muted to a video whose sound should play
|
|
-->
|
|
<video
|
|
id="el-video"
|
|
class="clip"
|
|
data-start="0"
|
|
data-duration="10"
|
|
data-track-index="0"
|
|
src="my-video.mp4"
|
|
data-has-audio="true"
|
|
playsinline
|
|
></video>
|
|
|
|
<!--
|
|
════════════════════════════════════════════════════
|
|
IMAGE CLIPS
|
|
════════════════════════════════════════════════════
|
|
|
|
data-duration is REQUIRED for images (they have no intrinsic duration).
|
|
-->
|
|
<img
|
|
id="el-image"
|
|
class="clip"
|
|
data-start="10"
|
|
data-duration="5"
|
|
data-track-index="0"
|
|
src="my-image.png"
|
|
/>
|
|
|
|
<!--
|
|
════════════════════════════════════════════════════
|
|
AUDIO
|
|
════════════════════════════════════════════════════
|
|
|
|
Audio is invisible — no class="clip" needed (no visual to hide).
|
|
Use <audio> for music, voiceover, or replacement sound. A video with sound
|
|
keeps it on the <video> (data-has-audio="true").
|
|
The framework syncs audio playback to the timeline position.
|
|
|
|
Optional: data-volume="0.5" (0-1, default 1)
|
|
-->
|
|
<audio
|
|
id="el-audio"
|
|
data-start="0"
|
|
data-duration="15"
|
|
data-track-index="1"
|
|
data-volume="0.8"
|
|
src="my-music.mp3"
|
|
></audio>
|
|
|
|
<!--
|
|
════════════════════════════════════════════════════
|
|
TEXT / HTML OVERLAYS
|
|
════════════════════════════════════════════════════
|
|
|
|
Any div with data-start becomes a timed clip.
|
|
Content inside can be freely styled with CSS.
|
|
Animate visual properties (opacity, transform) with GSAP — fine.
|
|
Do NOT animate visibility — the framework owns that.
|
|
-->
|
|
<div
|
|
id="el-title"
|
|
class="clip"
|
|
data-start="1"
|
|
data-duration="4"
|
|
data-track-index="2"
|
|
style="display: flex; align-items: center; justify-content: center; z-index: 10"
|
|
>
|
|
<h1 style="font-family: sans-serif; font-size: 72px; color: white; opacity: 0">
|
|
Hello World
|
|
</h1>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
/*
|
|
════════════════════════════════════════════════════
|
|
GSAP TIMELINE
|
|
════════════════════════════════════════════════════
|
|
|
|
REQUIRED: Create a paused GSAP timeline.
|
|
REQUIRED: Register it in window.__timelines with the SAME ID
|
|
as data-composition-id on the <meta> tag.
|
|
|
|
Without this registration, NOTHING works — no playback,
|
|
no seeking, no rendering. This is the #1 mistake.
|
|
*/
|
|
var tl = gsap.timeline({ paused: true });
|
|
|
|
// Animate visual properties only — opacity, transform, color, etc.
|
|
// The framework handles clip mounting/unmounting and media playback.
|
|
tl.to("#el-video", { opacity: 1, duration: 0.5 }, 0);
|
|
tl.to("#el-video", { opacity: 0, duration: 0.5 }, 9.5);
|
|
|
|
tl.to("#el-image", { opacity: 1, duration: 0.5 }, 10);
|
|
tl.to("#el-image", { opacity: 0, duration: 0.5 }, 14.5);
|
|
|
|
tl.to("#el-title h1", { opacity: 1, y: 0, duration: 0.8, ease: "power2.out" }, 1);
|
|
tl.to("#el-title h1", { opacity: 0, duration: 0.5 }, 4);
|
|
|
|
// REQUIRED: Register the timeline. The key MUST match data-composition-id.
|
|
window.__timelines = window.__timelines || {};
|
|
window.__timelines["my-video"] = tl;
|
|
</script>
|
|
</body>
|
|
</html>
|