A full reconstruction reported fourteen places the route cost it time. Twelve held. What is here is
the subset that changes the next run rather than the last one, and most of it is code: a fact stated
in a document is a fact every future reader has to carry, so where the tool could stop being wrong
instead, it does.
**The cut re-anchors instead of dropping.** An element given the span it occupies and a Moment to
close it — `during="program" until={story.moment.done}` — is on screen for the whole of any stretch
that ends before that word. `render_element` dropped it, so the one element a reference is about was
unrenderable over every Segment but the last, while the loop asks for it to be compared over each of
them. A close that has not arrived is now removed from the tag and the element stays. Marked before
the cut it really is gone, and marked inside it survived already. Measured on the run that found it:
one Segment renderable before, four after, and the two that still refuse now name a Producer failure
the drop was hiding.
**The package root comes from the Run.** It was the working directory, so naming a Run by path
resolved its imports somewhere else and the project's own elements read as packages that do not
exist. It is now the nearest `package.json` at or above the Run — the same walk `hypit check` makes.
`--package-root` still overrides it and is no longer needed to check a project from anywhere.
**The mock's frame is a hairline.** At a twentieth of the shorter side it was fifty pixels thick on a
full-frame mock, and an observer measuring what an element covers read that as the element stopping
short of the edge — reported every round, about the mock rather than about the Source.
**The comparison names its own pair.** The prompt asks for each difference to say which of the two it
is in, and `observers.md` says which is which: one is the reference, two is the render. The observer
is not told, and the caller was not either.
**`--reference-id` is in the command block** it was missing from, with what it decides. Six of the
run's first comparisons were refused for a mismatch this flag exists to prevent, and it was found by
grepping the tool's source.
Corrections that cost no length: `vocabulary.md` had the inspect output's shape wrong — Recipe
properties are inside the `recipe` attribute, not beside `attributes` — which is why the run read the
file's central claim as false. `styles.md` and `composition.md` documented two Cue keys the Style
refuses and a `display=` that is `document=`.
Two facts moved to where the reader already is rather than into the skill: `media-track`'s `extent`
summary says the ratio is what it decides, and `VisualElement` says position is measured from the
parent. The other runtime-only errors already name their own fix.
10 KiB
title, description
| title | description |
|---|---|
| Film & Rendering | Composing tracks into a film and rendering to video. |
Film & Rendering
Film is the final assembly stage. It takes all peer Tracks, validates them, and produces a Composition. The renderer then compiles that Composition into an MP4 video.
<import as="space" from="@hypit/spatial@1"/>
<import as="film" from="@hypit/film@1"/>
<import as="render" from="@hypit/render-hyperframes@1"/>
film:Film
Assembles all Tracks into a single Composition. Film itself has no domain knowledge — it does not know what a caption is, what Media is, or what speech is. It takes any VisualTrack or AudioTrack and layers them by stacking order.
<space:Canvas id="vertical" width="1080" height="1920"/>
<film:Film id="main" canvas={vertical} semantic={speech.semantic} appearance={recipes.film.vertical}>
<film:Track source={speech.visual}/>
<film:Track source={speech.audio}/>
<film:Track source={captions.track}/>
<film:Track source={product-broll.visual}/>
<film:Track source={titles.track}/>
</film:Film>
| Attribute | Required | Description |
|---|---|---|
id |
yes | Unique identifier |
canvas |
yes | Explicit CanvasSpace shared with Track layout |
semantic |
yes | SemanticTrack from speech:Track — defines duration and frame rate |
appearance |
yes | SVS Film Recipe — the canvas clear color |
film:Track
Each <film:Track> child adds a Track source to the composition:
| Attribute | Required | Description |
|---|---|---|
source |
yes | A VisualTrack or AudioTrack from any upstream component |
Common Track sources:
| Source | Type | From |
|---|---|---|
{speech.visual} |
VisualTrack | speech:Track — sparse same-source speech visuals |
{speech.audio} |
AudioTrack | speech:Track — synchronized audio |
{captions.track} |
VisualTrack | a Caption Style-family Track — timed captions |
{cards.visual} |
VisualTrack | media-track:Track — media overlays or B-roll |
{titles.track} |
VisualTrack | text:Track — text overlays |
Track stacking
Tracks are flat — there is no nesting or grouping. Z-ordering is determined entirely by the
stack-order property in each Track's SVS Recipe. Lower values go behind; higher values render on
top.
Typical stacking order:
| stack-order | Content |
|---|---|
| 10 | Example Speech visual (author-selected, not a built-in default) |
| 40 | Media overlays |
| 70 | Captions |
| 90 | Text overlays |
One component can emit multiple visual elements (Presents) at different z-positions, which interleave with other components' Presents. The final render flattens all Presents, sorts by absolute stacking key, and paints them onto one canvas.
Output: {main.composition} — the complete Composition, passed to the renderer.
render:Video
Compiles the Composition into a finished video via the HyperFrames renderer.
<render:Video id="final" composition={main.composition} semantic={speech.semantic}/>
| Attribute | Required | Description |
|---|---|---|
id |
yes | Unique identifier |
composition |
yes | Composition from film:Film |
semantic |
yes | SemanticTrack from speech:Track |
The renderer:
- Compiles the Composition into a
HyperframesDocument— an HTML representation of every frame - Renders each frame through Chrome/Chromium
- Encodes the frame sequence into video
- Mixes the audio Tracks
- Muxes video + audio into the final MP4
Output: {final.video} — the finished video as an ordinary content-addressed BlobArtifact.
This is the most common Build Target, and it can also be connected directly to later Blob consumers
such as media trimming, audio/frame extraction or a model reference input.
Full pipeline walkthrough
The complete data flow from Script to rendered video. This example is based on
examples/talking-film-graph-check/ — the smallest complete graph.
Author Source (main.svml)
<?svml using="@hypit/markup@1"?>
<svml>
<import from="@hypit/script@1"/>
<import as="wording" from="@hypit/text@1"/>
<import as="gpt" from="@hypit/gpt-image@1"/>
<import as="seedance" from="@hypit/seedance@1"/>
<import as="pipeline" from="@hypit/media-pipeline@1"/>
<import as="speech" from="@hypit/speech-track@1"/>
<import as="whisperx" from="@hypit/whisperx@1"/>
<import as="caption" from="@hypit/caption@1"/>
<import as="caption-fine" from="@hypit/caption-fine@1"/>
<import as="fonts" from="@hypit/fonts-open@1"/>
<import as="media-track" from="@hypit/media-track@1"/>
<import as="text" from="@hypit/typography-track@1"/>
<import as="space" from="@hypit/spatial@1"/>
<import as="program" from="@hypit/program-space@1"/>
<import as="film" from="@hypit/film@1"/>
<import as="render" from="@hypit/render-hyperframes@1"/>
<import as="recipes" source="./recipes.svs"/>
<!-- 1. Script: the semantic truth -->
<script id="story">
<opening><HOST>Meaning @demo becomes the source @/demo.</opening>
</script>
<!-- 2. Generation: Seedance talking head + standalone video -->
<wording:Value id="direction">
Locked medium close-up in a quiet daylight studio. Spoken dialogue — say exactly: Meaning becomes the source.
</wording:Value>
<wording:Value id="scene-look">
A photograph with the texture of real iPhone footage. Generate a vertical seated medium
close-up, as one frame cut out of video actually shot on an iPhone: genuinely real rather than
glossy, carrying the texture of video and not of a posed photograph. The background stays clearly
visible, with no depth-of-field blur. Skin texture is fine and real, the light is natural, and no
part of the picture is broken. One presenter at a desk in a quiet daylight studio.
</wording:Value>
<gpt:Image id="studio-scene" prompt={scene-look} aspect-ratio="9:16" resolution="2K"/>
<seedance:ReferenceVideo id="take" model="mini"
prompt={direction} duration="5" generate-audio="true">
<seedance:Reference image={studio-scene.image}/>
</seedance:ReferenceVideo>
<seedance:ReferenceVideo id="motion" model="mini"
prompt={direction} duration="5">
<seedance:Reference image={studio-scene.image}/>
</seedance:ReferenceVideo>
<space:Canvas id="vertical" width="1080" height="1920"/>
<program:Clock id="clock" frame-rate="30"/>
<space:Frame id="speech-frame" within={vertical}
left="0%" top="0%" right="100%" bottom="100%"/>
<space:Frame id="title-frame" within={vertical}
left="6%" top="6%" right="94%" bottom="16%"/>
<space:Frame id="card-frame" within={vertical}
left="10%" top="20%" right="90%" bottom="70%"/>
<!-- 3. Timing: normalize and align the Segment before assembly -->
<pipeline:Normalize id="take-media" source={take.video}
video="primary-moving" audio="default" span-authority="video" clock={clock}/>
<pipeline:Normalize id="motion-media" source={motion.video}
video="primary-moving" audio="none" span-authority="video" clock={clock}/>
<whisperx:SemanticTake id="opening-semantic" narrative={story}
segment={story.segment.opening} media={take-media.media} language="en"/>
<speech:Track id="speech"
visual-frame={speech-frame} visual-appearance={recipes.speech.visual} visual-z="0">
<speech:Take source={opening-semantic.take}/>
</speech:Track>
<!-- 4. Tracks: captions, Media, text -->
<fonts:Stack id="caption-font" family="inter" weight="700" style="normal"/>
<fonts:Stack id="title-font" family="inter" weight="900" style="normal"/>
<caption-fine:Style id="base-caption" recipe={recipes.caption.base} font={caption-font}/>
<caption:Program id="caption-program" document={story.caption} narrative={story}
default={base-caption}/>
<caption-fine:Track id="captions" document={story.caption}
semantic={speech.semantic} program={caption-program}/>
<media-track:Track id="cards" semantic={speech.semantic} canvas={vertical}>
<media-track:Item media={motion-media.media} during={story.selection.demo}
frame={card-frame} appearance={recipes.media.card} motion={recipes.motion.card}/>
</media-track:Track>
<text:Style id="title-style" recipe={recipes.text.title} font={title-font}/>
<text:Track id="titles" semantic={speech.semantic}>
<text:Area id="meaning" placement={title-frame} style={title-style} during="program">
MEANING
</text:Area>
</text:Track>
<!-- 5. Film: compose all tracks -->
<film:Film id="main" canvas={vertical} semantic={speech.semantic}
appearance={recipes.film.vertical}>
<film:Track source={speech.visual}/>
<film:Track source={speech.audio}/>
<film:Track source={cards.visual}/>
<film:Track source={captions.track}/>
<film:Track source={titles.track}/>
</film:Film>
<!-- 6. Render: compile to MP4 -->
<render:Video id="final" composition={main.composition}
semantic={speech.semantic}/>
</svml>
right and bottom are absolute edge positions, not insets. A Frame spanning the middle 80% of
its parent is left="10%" right="90%", not left="10%" right="10%" — the second resolves to zero
width and is rejected.
Stylesheet (recipes.svs)
<?svml using="@hypit/svs@1"?>
<sheet version="1">
film.vertical {
background: #09090B;
}
speech.visual { fit: cover; }
media.card {
stack-order: 40; fit: cover; playback: hold-start;
frame-paint: #111116; clip: rounded; radius: 20;
}
motion.card {
enter: slide; enter-frames: 4; enter-direction: up; enter-easing: ease-out;
exit: fade; exit-frames: 4; exit-easing: ease-in;
}
caption.base {
stack-order: 70; x: 0.08; y: 0.76; width: 0.84;
size: 58; line-height: 1; align: center;
fill: #FFFFFF; background: #09090BCC; padding: 16 24; radius: 18;
}
text.title {
stack-order: 90;
font: Inter; weight: 900; size: 64; align: center;
fill: #FFFFFF; tracking: -1;
}
</sheet>
Run Source (build.svrun)
<?svml using="@hypit/run-markup@1"?>
<svrun version="1">
<author source="./main.svml"/>
<target output="final.video"/>
</svrun>
Compile and verify
hypit check examples/talking-film-graph-check/main.svml
hypit plan examples/talking-film-graph-check/build.svrun
check compiles the Author Graph — validates all imports, types, and graph edges without calling
any external service. plan additionally compiles the Run Source and outputs the frozen BuildPlan
showing every Operation the Scheduler would issue. Inspect the plan before spending money.