Skip to content

Commit b3071e3

Browse files
committed
docs(concepts): clarify what can and can't be a variable
1 parent f4e96a5 commit b3071e3

3 files changed

Lines changed: 66 additions & 0 deletions

File tree

docs/concepts/variables.mdx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,64 @@ Every declaration requires four fields: `id`, `type`, `label`, and `default`. `i
3434

3535
The Studio editing UI uses `label`, `type`, and the type-specific options to render the right input widget for each variable.
3636

37+
## What can be a variable
38+
39+
Variables come in two layers. The five [declared types](#variable-types) above cover typed primitive data — strings, numbers, colors, booleans, enums. For everything else, a `string` variable holding a URL is the escape hatch: your composition reads the URL and assigns it to whatever DOM element needs it.
40+
41+
### Parameterizing media assets
42+
43+
The same composition can render different images, video clips, or audio tracks just by swapping URLs through a string variable:
44+
45+
```html compositions/product-card.html
46+
<html data-composition-variables='[
47+
{"id":"productImage","type":"string","label":"Product image URL","default":"https://cdn.example.com/products/default.png"},
48+
{"id":"productName","type":"string","label":"Product name","default":"Untitled"}
49+
]'>
50+
<body>
51+
<div data-composition-id="product-card" data-width="1920" data-height="1080" data-duration="5">
52+
<img class="product-img" alt="" />
53+
<h1 class="product-name"></h1>
54+
55+
<script>
56+
const {
57+
productImage = "https://cdn.example.com/products/default.png",
58+
productName = "Untitled",
59+
} = __hyperframes.getVariables();
60+
const root = document.querySelector('[data-composition-id="product-card"]');
61+
root.querySelector(".product-img").src = productImage;
62+
root.querySelector(".product-name").textContent = productName;
63+
</script>
64+
</div>
65+
</body>
66+
</html>
67+
```
68+
69+
<Note>
70+
The runtime probes the DOM after your composition script runs, so a `<video>` or `<audio>` `src` assigned at runtime from a variable is discovered and pre-extracted for the render. No extra wiring required — just set the `src` from your variable.
71+
</Note>
72+
73+
The same pattern covers the three media element types:
74+
75+
- **`<img src>`** — assign from a string variable. Chrome fetches it during capture like any other image; no extra config.
76+
- **`<video src>`** — assign from a string variable, but keep the timing attributes (`data-start`, `data-duration`, `data-track-index`, `data-has-audio`) on the element itself. The probe phase scans `video[data-start]` elements after your script runs and reads the resolved `src` for pre-extraction.
77+
- **`<audio src>`** — same as video. The audio is decoded during capture and mixed into the final output.
78+
79+
Pass assets as URL references your composition resolves at render time; don't inline base64. URL-shaped assets travel cleanly through both the local renderer and the Lambda surface — see [Templates on Lambda](/deploy/templates-on-lambda#working-with-large-variables) for the 256 KiB execution-input cap on distributed renders.
80+
81+
## What can't be a variable
82+
83+
Some inputs look variable-shaped but are configured elsewhere. The right mechanism for each:
84+
85+
| What | Mechanism (not a variable) |
86+
|------|----------------------------|
87+
| Composition duration | `data-duration` attribute on the composition element |
88+
| Composition dimensions | `data-width` / `data-height` attributes |
89+
| Frame rate | `--fps` flag on `hyperframes render` |
90+
| Output format / codec / quality | `--format` / `--codec` / `--quality` flags |
91+
| A sibling or parent composition's variables | Variables are per-composition; use [`data-variable-values`](#per-instance-overrides-sub-compositions) on each sub-comp host element to pass overrides |
92+
93+
The deeper rule: variables are runtime values, not authoring inputs. A variable can toggle DOM state, swap text, change a color — anything your composition script does with the resolved value. It can't change the composition's structural identity. Two compositions with different `data-composition-id` or different layout markup remain different compositions, even when their variable values are identical.
94+
3795
## Reading Variables at Runtime
3896

3997
Inside any composition script, call `window.__hyperframes.getVariables()` to get the resolved variable values. The return type is `Partial<Record<string, unknown>>` — use destructuring with defaults matching the declared `default` values:

docs/deploy/aws-lambda.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ hyperframes lambda render ./my-project --width 1920 --height 1080 --wait
1111
hyperframes lambda destroy
1212
```
1313

14+
Templates with [variables](/concepts/variables) work on the same Lambda stack — declare `data-composition-variables` on the composition, then pass values per render with `--variables` or fan a whole batch out with `lambda render-batch`. See the [Templates on Lambda](/deploy/templates-on-lambda) guide for the personalised-render pipeline (single render, batch from JSONL, programmatic SDK) and the 256 KiB Step Functions execution-input cap.
15+
1416
## Architecture
1517

1618
```

docs/deploy/migrating-to-hyperframes-lambda.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ Most adopters' render config maps directly:
4848
| Max parallel chunks | `--max-parallel-chunks=16` (default 16) | Caps the Map state's fan-out. |
4949
| Bitrate / CRF | `--bitrate=10M` or `--crf=18` | Mutually exclusive. |
5050

51+
## Variables (inputProps)
52+
53+
Render-time payloads — `inputProps` in some frameworks, `variables` in HyperFrames — are isomorphic. Declare the composition's variable shape on the root `<html>` element via `data-composition-variables`, then pass per-render values with `hyperframes render --variables '{...}'` locally or `hyperframes lambda render --variables` on the Lambda surface. The same 256 KiB execution-input cap and "URL your assets, don't inline base64" convention apply.
54+
55+
The full mapping — `defaultProps` → declarations, `useCurrentFrame()` + `props.<x>``__hyperframes.getVariables().<x>`, `renderMediaOnLambda({ inputProps })``renderToLambda({ config: { variables } })` — lives in [Templates on Lambda](/deploy/templates-on-lambda#migrating-from-remotion-lambda-inputprops).
56+
5157
## What HyperFrames does differently
5258

5359
A few areas where the contract is intentionally different from comparable frameworks. Surface them up front so the migration doesn't surprise you mid-deploy.

0 commit comments

Comments
 (0)