mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-01 19:42:03 +00:00
Major improvements across all 18 pages: - Use Mintlify components: <Steps> for tutorials, <Tabs> for alternatives, <CodeGroup> for multi-platform commands, <Tree> for directory structures, <AccordionGroup> for FAQ/scannable content, <Mermaid> for diagrams - Add filename annotations to all code blocks (e.g., ```html index.html) - Add numbered comments inside multi-step code examples - Show expected terminal output after CLI commands - Add "When to use" / "When NOT to use" sections to all package pages - Add "Next Steps" CardGroup to every page (no dead-end pages) - Cross-link between pages at point of curiosity (not just "see also" dumps) - Expand thin pages (engine, studio) with architecture details and examples - Add decision guides (rendering modes, template selection) - Use <Warning> and <Note> sparingly (max 2-3 per page) Also adds DOCS_GUIDELINES.md at repo root with writing standards. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
145 lines
4.6 KiB
Plaintext
145 lines
4.6 KiB
Plaintext
---
|
|
title: Frame Adapters
|
|
description: "Bring your own animation runtime to Hyperframes."
|
|
---
|
|
|
|
The Frame Adapter pattern is how Hyperframes supports multiple animation runtimes. The core question every adapter answers:
|
|
|
|
> What should the screen look like at frame N?
|
|
|
|
If a runtime can answer that, it can plug into Hyperframes.
|
|
|
|
<Info>
|
|
The Adapter API is currently at **v0** (experimental). Breaking changes are possible until v1. The core contract (seek-by-frame, deterministic output) is stable, but method signatures may evolve.
|
|
</Info>
|
|
|
|
## How It Works
|
|
|
|
The host application (the [engine](/packages/engine) or [producer](/packages/producer)) drives rendering by calling adapter methods in a strict sequence. The adapter never controls its own clock -- it only responds to seek commands.
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Host as Host (Engine)
|
|
participant Adapter as Frame Adapter
|
|
participant Chrome as Chrome / Browser
|
|
|
|
Host->>Adapter: init(context)
|
|
Adapter-->>Host: ready
|
|
Host->>Adapter: getDurationFrames()
|
|
Adapter-->>Host: 300 frames
|
|
|
|
loop For each frame 0..300
|
|
Host->>Host: normalize frame (clamp, floor)
|
|
Host->>Adapter: seekFrame(frame)
|
|
Adapter->>Chrome: Update DOM / canvas state
|
|
Adapter-->>Host: done
|
|
Host->>Chrome: Capture pixel buffer
|
|
end
|
|
|
|
Host->>Adapter: destroy()
|
|
Adapter-->>Host: cleaned up
|
|
```
|
|
|
|
## Adapter API (v0)
|
|
|
|
```typescript adapters/types.ts
|
|
type FrameAdapterContext = {
|
|
compositionId: string;
|
|
fps: number;
|
|
width: number;
|
|
height: number;
|
|
rootElement?: HTMLElement;
|
|
};
|
|
|
|
type FrameAdapter = {
|
|
id: string;
|
|
init?: (ctx: FrameAdapterContext) => Promise<void> | void;
|
|
getDurationFrames: () => number;
|
|
seekFrame: (frame: number) => Promise<void> | void;
|
|
destroy?: () => Promise<void> | void;
|
|
};
|
|
```
|
|
|
|
## Required Semantics
|
|
|
|
- `getDurationFrames()` must return a finite integer >= 0
|
|
- `seekFrame(frame)` must support arbitrary seek order (forward, backward, random)
|
|
- `seekFrame(frame)` must be idempotent for the same input frame
|
|
- `seekFrame(frame)` must clamp internal time to the adapter's range
|
|
- Adapters should be paused/seek-driven, not clock-driven
|
|
|
|
## Host Orchestration
|
|
|
|
The host normalizes frames before calling the adapter:
|
|
|
|
```typescript engine/render-loop.ts
|
|
normalizedFrame = clamp(Math.floor(frame), 0, durationFrames);
|
|
```
|
|
|
|
A typical render loop:
|
|
|
|
```typescript engine/render-loop.ts
|
|
await adapter.init?.({ compositionId, fps, width, height, rootElement });
|
|
const durationFrames = adapter.getDurationFrames();
|
|
|
|
for (let frame = 0; frame <= durationFrames; frame += 1) {
|
|
await adapter.seekFrame(frame);
|
|
// capture pixel buffer for this frame
|
|
}
|
|
|
|
await adapter.destroy?.();
|
|
```
|
|
|
|
## Determinism Contract
|
|
|
|
These rules are non-negotiable for any adapter. They are the foundation of Hyperframes' [deterministic rendering](/concepts/determinism) guarantee.
|
|
|
|
- Canonical clock: `t = frame / fps`
|
|
- No wall-clock dependencies (`Date.now`, drift-dependent logic)
|
|
- No unseeded randomness
|
|
- No render-time network fetches
|
|
- Fixed output params (`fps`, `width`, `height`)
|
|
- Finite duration only
|
|
- Deterministic frame quantization before seek
|
|
|
|
## Supported Runtimes
|
|
|
|
First-party adapters:
|
|
|
|
| Runtime | Seek Method | Status |
|
|
|---------|------------|--------|
|
|
| [GSAP](/guides/gsap-animation) | `timeline.seek(frame / fps)` | Available |
|
|
| CSS/WAAPI | `animation.currentTime` | Planned |
|
|
| Lottie | Set animation frame/progress | Planned |
|
|
| Three.js/WebGL | Compute deterministic scene state | Planned |
|
|
| SVG/Anime | Implement seek + duration contract | Planned |
|
|
|
|
Community adapters are welcome -- if it can seek by frame, it belongs in Hyperframes.
|
|
|
|
## Conformance Tests
|
|
|
|
Every adapter should pass these minimum tests:
|
|
|
|
1. **Repeatability** -- seek same frame twice, get identical output
|
|
2. **Random seek** -- seek order `[90, 10, 50, 10]` produces deterministic results
|
|
3. **Bounds** -- negative and overflow frame values do not break
|
|
4. **Duration** -- returned duration is a finite integer
|
|
5. **Cleanup** -- no leaked timers/listeners after `destroy`
|
|
|
|
## Next Steps
|
|
|
|
<CardGroup cols={2}>
|
|
<Card title="Deterministic Rendering" icon="lock" href="/concepts/determinism">
|
|
Understand the determinism guarantees adapters must uphold
|
|
</Card>
|
|
<Card title="GSAP Animation" icon="wand-magic-sparkles" href="/guides/gsap-animation">
|
|
See the first-party GSAP adapter in action
|
|
</Card>
|
|
<Card title="@hyperframes/engine" icon="gear" href="/packages/engine">
|
|
The capture engine that drives adapters during rendering
|
|
</Card>
|
|
<Card title="Contributing" icon="code-branch" href="/contributing">
|
|
Build and contribute your own adapter
|
|
</Card>
|
|
</CardGroup>
|