frameyard 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +101 -0
- package/GLOSSARY.md +156 -24
- package/README.md +103 -31
- package/dist/cli.js +112 -19
- package/dist/cli.js.map +1 -1
- package/dist/composition/adapter.d.ts +30 -0
- package/dist/composition/adapter.d.ts.map +1 -0
- package/dist/composition/adapter.js +2 -0
- package/dist/composition/adapter.js.map +1 -0
- package/dist/composition/animation.d.ts +19 -0
- package/dist/composition/animation.d.ts.map +1 -0
- package/dist/composition/animation.js +55 -0
- package/dist/composition/animation.js.map +1 -0
- package/dist/composition/attributes.d.ts +7 -0
- package/dist/composition/attributes.d.ts.map +1 -0
- package/dist/composition/attributes.js +24 -0
- package/dist/composition/attributes.js.map +1 -0
- package/dist/composition/descriptor.d.ts +30 -0
- package/dist/composition/descriptor.d.ts.map +1 -0
- package/dist/composition/descriptor.js +188 -0
- package/dist/composition/descriptor.js.map +1 -0
- package/dist/composition/diagnostics.d.ts +12 -0
- package/dist/composition/diagnostics.d.ts.map +1 -0
- package/dist/composition/diagnostics.js +38 -0
- package/dist/composition/diagnostics.js.map +1 -0
- package/dist/composition/index.d.ts +12 -0
- package/dist/composition/index.d.ts.map +1 -0
- package/dist/composition/index.js +7 -0
- package/dist/composition/index.js.map +1 -0
- package/dist/composition/media.d.ts +27 -0
- package/dist/composition/media.d.ts.map +1 -0
- package/dist/composition/media.js +162 -0
- package/dist/composition/media.js.map +1 -0
- package/dist/composition/paths.d.ts +5 -0
- package/dist/composition/paths.d.ts.map +1 -0
- package/dist/composition/paths.js +16 -0
- package/dist/composition/paths.js.map +1 -0
- package/dist/composition/transcripts.d.ts +19 -0
- package/dist/composition/transcripts.d.ts.map +1 -0
- package/dist/composition/transcripts.js +57 -0
- package/dist/composition/transcripts.js.map +1 -0
- package/dist/composition/walk.d.ts +10 -0
- package/dist/composition/walk.d.ts.map +1 -0
- package/dist/composition/walk.js +32 -0
- package/dist/composition/walk.js.map +1 -0
- package/dist/contracts.d.ts +14 -0
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/html/document-adapter.d.ts +5 -0
- package/dist/html/document-adapter.d.ts.map +1 -0
- package/dist/html/document-adapter.js +17 -0
- package/dist/html/document-adapter.js.map +1 -0
- package/dist/html/parse.d.ts +2 -6
- package/dist/html/parse.d.ts.map +1 -1
- package/dist/html/parse.js.map +1 -1
- package/dist/html/validate.d.ts.map +1 -1
- package/dist/html/validate.js +92 -375
- package/dist/html/validate.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/preview/main.d.ts.map +1 -1
- package/dist/preview/main.js +93 -13
- package/dist/preview/main.js.map +1 -1
- package/dist/preview/timeline-data.d.ts +85 -0
- package/dist/preview/timeline-data.d.ts.map +1 -0
- package/dist/preview/timeline-data.js +2 -0
- package/dist/preview/timeline-data.js.map +1 -0
- package/dist/preview/timeline-host.d.ts +19 -0
- package/dist/preview/timeline-host.d.ts.map +1 -0
- package/dist/preview/timeline-host.js +297 -0
- package/dist/preview/timeline-host.js.map +1 -0
- package/dist/preview/timeline-main.d.ts +17 -0
- package/dist/preview/timeline-main.d.ts.map +1 -0
- package/dist/preview/timeline-main.js +364 -0
- package/dist/preview/timeline-main.js.map +1 -0
- package/dist/project.d.ts +16 -1
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +81 -26
- package/dist/project.js.map +1 -1
- package/dist/renderer/browser.d.ts +2 -0
- package/dist/renderer/browser.d.ts.map +1 -1
- package/dist/renderer/browser.js +38 -6
- package/dist/renderer/browser.js.map +1 -1
- package/dist/renderer/ffmpeg.d.ts +61 -0
- package/dist/renderer/ffmpeg.d.ts.map +1 -1
- package/dist/renderer/ffmpeg.js +198 -0
- package/dist/renderer/ffmpeg.js.map +1 -1
- package/dist/renderer/index.d.ts.map +1 -1
- package/dist/renderer/index.js +18 -7
- package/dist/renderer/index.js.map +1 -1
- package/dist/renderer/timeline.d.ts +109 -0
- package/dist/renderer/timeline.d.ts.map +1 -0
- package/dist/renderer/timeline.js +984 -0
- package/dist/renderer/timeline.js.map +1 -0
- package/dist/runtime/document-adapter.d.ts +4 -0
- package/dist/runtime/document-adapter.d.ts.map +1 -0
- package/dist/runtime/document-adapter.js +19 -0
- package/dist/runtime/document-adapter.js.map +1 -0
- package/dist/runtime/host.d.ts +2 -0
- package/dist/runtime/host.d.ts.map +1 -1
- package/dist/runtime/host.js +78 -183
- package/dist/runtime/host.js.map +1 -1
- package/dist/runtime/media.d.ts.map +1 -1
- package/dist/runtime/media.js +19 -50
- package/dist/runtime/media.js.map +1 -1
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +93 -23
- package/dist/scaffold.js.map +1 -1
- package/dist/server/preview-html.d.ts.map +1 -1
- package/dist/server/preview-html.js +15 -1
- package/dist/server/preview-html.js.map +1 -1
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +39 -1
- package/dist/server/server.js.map +1 -1
- package/dist/server/timeline-preview-data.d.ts +4 -0
- package/dist/server/timeline-preview-data.d.ts.map +1 -0
- package/dist/server/timeline-preview-data.js +97 -0
- package/dist/server/timeline-preview-data.js.map +1 -0
- package/dist/server/timeline-preview-html.d.ts +4 -0
- package/dist/server/timeline-preview-html.d.ts.map +1 -0
- package/dist/server/timeline-preview-html.js +227 -0
- package/dist/server/timeline-preview-html.js.map +1 -0
- package/dist/timeline/plan.d.ts +32 -0
- package/dist/timeline/plan.d.ts.map +1 -0
- package/dist/timeline/plan.js +68 -0
- package/dist/timeline/plan.js.map +1 -0
- package/dist/timeline/resolve.d.ts +60 -0
- package/dist/timeline/resolve.d.ts.map +1 -0
- package/dist/timeline/resolve.js +523 -0
- package/dist/timeline/resolve.js.map +1 -0
- package/dist/timeline/schema.d.ts +71 -0
- package/dist/timeline/schema.d.ts.map +1 -0
- package/dist/timeline/schema.js +425 -0
- package/dist/timeline/schema.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/adr/0002-make-frame-and-props-the-only-animation-state.md +2 -0
- package/docs/adr/0005-keep-parallel-rendering-opt-in-and-frame-ordered.md +2 -0
- package/docs/adr/0006-seek-embedded-media-from-the-frame-clock.md +4 -0
- package/docs/adr/0007-make-html-documents-the-composition-unit.md +1 -1
- package/docs/adr/0008-share-the-composition-document-grammar.md +18 -0
- package/docs/adr/0009-composite-production-frames-in-software.md +37 -0
- package/docs/adr/0010-make-timelines-the-render-unit.md +24 -0
- package/docs/adr/0011-compose-timeline-frames-in-a-live-browser-host.md +22 -0
- package/docs/adr/0012-render-timelines-with-segmented-lossless-clip-intermediates.md +31 -0
- package/docs/v0.1-design.md +135 -85
- package/examples/demo/README.md +11 -4
- package/examples/demo/timelines/demo.timeline.json +12 -0
- package/examples/demo/video.config.js +4 -0
- package/examples/video/README.md +105 -0
- package/examples/video/assets/clip.mp4 +0 -0
- package/examples/video/assets/clip.webm +0 -0
- package/examples/video/compositions/video-mp4.html +362 -0
- package/examples/video/compositions/video-overlay.html +350 -0
- package/examples/video/compositions/video.html +362 -0
- package/examples/video/props/video-timeline.json +10 -0
- package/examples/video/props/video.json +8 -0
- package/examples/video/scripts/make-clip.sh +109 -0
- package/examples/video/timelines/video-timeline-mp4.timeline.json +44 -0
- package/examples/video/timelines/video-timeline.timeline.json +44 -0
- package/examples/video/video.config.js +12 -0
- package/examples/webgl/README.md +30 -0
- package/examples/webgl/compositions/webgl.controller.js +200 -0
- package/examples/webgl/compositions/webgl.html +215 -0
- package/examples/webgl/props/webgl.json +6 -0
- package/examples/webgl/video.config.js +5 -0
- package/package.json +4 -2
- package/skills/frameyard/SKILL.md +18 -13
- package/skills/frameyard/references/json-results.md +2 -2
- package/skills/frameyard/references/timelines.md +141 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Render timelines with segmented lossless clip intermediates
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-10-31
|
|
5
|
+
|
|
6
|
+
Timeline rendering will be segmented and parallel. For each segment, Chromium renders the active composition and nested-timeline clips to lossless FFV1 intermediates; FFmpeg decodes media, applies the clip's fit and static transform, composites the segment, encodes H.264, and the ordered segments are concatenated without re-encoding. Audio is mixed once for the whole timeline and muxed at the end. Preview remains a live Chromium timeline host with a bounded pool of active clips; parity is guaranteed at clip capture, not at the final composite.
|
|
7
|
+
|
|
8
|
+
The production target is a representative 60-minute 1920×1080 30 fps timeline with up to three active layers, a roughly 50/50 composition/media split by layer-seconds, 60% one layer, 30% two layers, and 10% three layers. The measured 10-second segment (two compositions, video, image) captured in 10.7 s, produced 35.2 MB of FFV1, and composited plus encoded in 6.1 s. A continuous three-layer composition-heavy 60-second gate took 52.4 s, and a continuous 50/50 full-frame video-overlay gate took 58.5 s; both extrapolate to about 1× real time and are documented as worst-case behavior, not the target workload. The representative 60-second gate — 50/50 layer-seconds, 60/30/10 occupancy, eight segments, four workers, and a 1080p video fast path — took 29.39 s and produced exactly 1800 frames at 30 fps, extrapolating to about 29.4 minutes for 60 minutes. The full 60-minute gate (2026-11-01) rendered a composition-only stress timeline of 108,000 frames, 120 composition clips, 360 segments, and four workers in 2,120.9 s (35.35 minutes). The output was exactly 108,000 frames / 3,600.000 s at 1920×1080, 30 fps, with scratch cleaned. That gate is stricter than the 50/50 target mix because every second is an HTML composition capture; it exceeds 30 minutes by 18%. The target is therefore met for the representative 50/50 workload, with little margin, while composition-heavy timelines run at roughly 1.7× real time.
|
|
9
|
+
|
|
10
|
+
The 1.8 TB USB HDD provides enough scratch capacity; a raw-frame cache would be roughly 670–900 GB, which does not fit, which is why the design uses compressed lossless FFV1 rather than raw frames or PNG sequences.
|
|
11
|
+
|
|
12
|
+
## Considered Options
|
|
13
|
+
|
|
14
|
+
- **Live browser host (ADR 0011).** Rejected: deterministic and pixel-exact, but 138.8 ms per 1920×1080 frame with four layers versus 33.6 ms for a direct composition capture. It does not meet the long-timeline target.
|
|
15
|
+
- **Skia + FFmpeg streaming compositor.** Rejected for 0.6: it avoids intermediates and preserves capture pixels, but adds a large compositor dependency and a custom frame pipeline. The FFmpeg + FFV1 path already meets the target without it. Skia remains an option if future effects or blend modes outgrow FFmpeg filters.
|
|
16
|
+
- **FFmpeg streaming through pipes.** Rejected: avoids intermediates and dependencies, but requires a fragile cross-platform multi-pipe/filter-graph coordination for a variable set of active layers.
|
|
17
|
+
- **Pre-render every clip for the whole timeline.** Rejected: for 60 minutes the intermediates can be tens to hundreds of gigabytes and the write/read time alone can exceed the render budget. Segmentation bounds peak scratch and lets workers run in parallel.
|
|
18
|
+
- **Lossy intermediates.** Rejected as the default: an extra lossy encode breaks pixel parity at clip capture. FFV1 keeps the captured frames exact; only the final H.264 encode is lossy, as it already is for composition renders.
|
|
19
|
+
|
|
20
|
+
## Consequences
|
|
21
|
+
|
|
22
|
+
- Composition and nested-timeline clips are captured with Chromium; media clips are decoded directly by FFmpeg. The timeline compositor is FFmpeg, not the browser.
|
|
23
|
+
- Composition clips that are transparent must be captured with a transparent browser background (`Emulation.setDefaultBackgroundColorOverride` with alpha 0); otherwise the top-level canvas produces a white background. FFV1 uses a pixel format that preserves alpha.
|
|
24
|
+
- Segments are bounded by active-layer changes or a maximum duration (10 s in the benchmark) so each segment has a fixed filter graph; segments are encoded with identical settings and concatenated with `-c copy`.
|
|
25
|
+
- Full-frame video clips with no transform or opacity that already match the project format and whose segment boundaries fall on source keyframes may be stream-copied instead of re-encoded. Other media is scaled/transformed/re-encoded. The representative gate's 29.4-minute projection includes this fast path and excludes any source-transcode time.
|
|
26
|
+
- Timeline workers are bounded (8 by default on the reference machine) and scratch is configurable and cleaned on success and failure. A 60-minute render should not depend on the system `/tmp` tmpfs.
|
|
27
|
+
- Nested timelines are rendered recursively to segment intermediates and treated as one layer, so parent opacity and transform apply to the grouped result. Cycles are rejected statically.
|
|
28
|
+
- Audio is mixed globally rather than per segment, avoiding boundary clicks and keeping clip trims/gains exact.
|
|
29
|
+
- `check` and `still` use the clip capture + timeline composite path for the requested frame; the long-form render path is not used to produce a single still.
|
|
30
|
+
- Preview uses a live Chromium timeline host with a small active-clip pool. Scaling, alpha, and video color conversion may differ from the final FFmpeg composite; the reproducibility guarantee is at clip capture.
|
|
31
|
+
- The 60-second, three-layer, audio-enabled benchmark is the gate before production implementation. A continuous three-layer composition-heavy run measured 52.4 s for 60 s, and a continuous 50/50 full-frame video-overlay run measured 58.5 s; both are about 1× real time and are documented as worst-case. The representative 50/50, 60/30/10 occupancy gate measured 29.39 s for 60 s with four workers and a 1080p media fast path, extrapolating to about 29.4 minutes for 60 minutes with exact 1800-frame output. The full 60-minute, composition-only gate completed in 35.35 minutes with exact 108,000-frame output; composition-heavy performance remains above the 30-minute target. If stricter composition-heavy performance is required, the next levers are a faster lossless intermediate codec, persistent capture sessions, and encoder preset/thread tuning.
|
package/docs/v0.1-design.md
CHANGED
|
@@ -2,154 +2,196 @@
|
|
|
2
2
|
|
|
3
3
|
**Status:** Accepted
|
|
4
4
|
**Initial acceptance:** 2026-10-27
|
|
5
|
-
**Last design revision:** 2026-10-
|
|
5
|
+
**Last design revision:** 2026-10-31
|
|
6
6
|
|
|
7
|
-
This document records the decisions confirmed during design sessions. It is the living product and architecture baseline; later changes revise this document explicitly rather than silently broaden the scope. The original v0.1 baseline has been revised through 0.
|
|
7
|
+
This document records the decisions confirmed during design sessions. It is the living product and architecture baseline; later changes revise this document explicitly rather than silently broaden the scope. The original v0.1 baseline has been revised through 0.6. Architecture decisions that changed the baseline are recorded in `docs/adr/`.
|
|
8
8
|
|
|
9
9
|
## 1. Product contract
|
|
10
10
|
|
|
11
|
-
Frameyard is a local-first, open-source framework for frontend developers and creative coders who build
|
|
11
|
+
Frameyard is a local-first, open-source framework for frontend developers and creative coders who build parameterized videos with HTML, CSS, and JavaScript. It separates reusable, prop-parameterized compositions from the timelines that assemble compositions and media into one video. AI agents can perform the same workflows on a user's behalf through an official skill.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Its differentiator is web-native authoring combined with deterministic, frame-accurate output and an explicit timeline model—not a React-centric composition model or a feature-for-feature clone of an existing NLE.
|
|
14
|
+
|
|
15
|
+
The target use cases are product demos, social clips, animated diagrams, data visualizations, karaoke-style subtitles, personalized videos, and long-form edits up to roughly 60 minutes. Professional collaborative editing, cloud production, and broadcast workflows remain outside the target audience.
|
|
14
16
|
|
|
15
17
|
The core success criterion is an end-to-end example in which a developer can:
|
|
16
18
|
|
|
17
|
-
1. Create
|
|
18
|
-
2. Animate
|
|
19
|
+
1. Create reusable, 1920×1080 HTML compositions with fixed metadata.
|
|
20
|
+
2. Animate them with HTML, CSS, SVG, and, where needed, a seek-safe controller for Canvas 2D and WebGL.
|
|
19
21
|
3. Supply JSON props and synchronized audio.
|
|
20
|
-
4.
|
|
21
|
-
5.
|
|
22
|
+
4. Assemble compositions and local media into a timeline with tracks, clips, trims, layers, and nested timelines.
|
|
23
|
+
5. Preview and scrub the timeline interactively.
|
|
24
|
+
6. Render it reproducibly to MP4 without dropped frames or timing drift.
|
|
25
|
+
7. Render a 60-minute timeline with up to three active layers within the long-form performance target.
|
|
22
26
|
|
|
23
|
-
The agent-enabled success criterion additionally requires an agent using the official skill to create and preserve a valid source project, optionally produce local audio and transcript assets, validate and inspect the
|
|
27
|
+
The agent-enabled success criterion additionally requires an agent using the official skill to create and preserve a valid source project, optionally produce local audio and transcript assets, validate and inspect the timeline and its compositions, render it, and report all resulting artifact paths without concealing validation failures or skipped visual review.
|
|
24
28
|
|
|
25
29
|
## 2. Project and authoring model
|
|
26
30
|
|
|
31
|
+
### Project
|
|
32
|
+
|
|
27
33
|
- Projects use ordinary HTML, CSS, static assets, and native JavaScript controllers, either inline in a composition document or in external modules.
|
|
28
|
-
- `video.config.js` explicitly
|
|
29
|
-
-
|
|
34
|
+
- `video.config.js` explicitly maps project IDs to source files. There is no directory scanning. It has three optional maps:
|
|
35
|
+
- `format`: the project's fixed `width`, `height`, and `fps`.
|
|
36
|
+
- `compositions`: IDs mapped to `.html` composition documents.
|
|
37
|
+
- `timelines`: IDs mapped to JSON timeline documents.
|
|
38
|
+
- `format` is required when a project has timelines. Every timeline uses it. A composition used in a timeline must share the project frame rate exactly; a different size is fitted and transformed by the clip. A standalone composition render keeps using the composition's own metadata.
|
|
39
|
+
- Composition and timeline IDs share one namespace so `render <id>`, `check <id>`, and `still <id>` are unambiguous. The config rejects duplicates.
|
|
40
|
+
- A project may contain any number of compositions and timelines.
|
|
41
|
+
|
|
42
|
+
### Composition
|
|
43
|
+
|
|
30
44
|
- A composition is a full HTML document with one `<fy-composition>` root. The root declares fixed `width`, `height`, `fps`, and `duration-in-frames` metadata. Props cannot change this metadata.
|
|
31
|
-
- Default props are a JSON block, `<script type="application/json" data-fy="props">`. A
|
|
45
|
+
- Default props are a JSON block, `<script type="application/json" data-fy="props">`. A load's JSON props merge shallowly over the defaults, are validated as JSON, deep-frozen, and fixed for that load.
|
|
32
46
|
- Props bind into the document through explicit `data-fy-*` attributes: `data-fy-text`, `data-fy-attr-*`, `data-fy-class-*`, `data-fy-if`, and `data-fy-repeat`. Primitive top-level props are also exposed as `--fy-prop-<name>` CSS custom properties. Bindings apply once per load; props are immutable.
|
|
33
47
|
- CSS and the Web Animations API are the animation language. `data-fy-anim-start`, `data-fy-anim-duration`, and `data-fy-anim-easing` schedule one animation per element in composition frames.
|
|
34
|
-
- An optional composition controller is declared with `<script type="text/fy-controller">`. It is either inline source or an external module referenced by `src`; a composition has exactly one controller. It may export `mount
|
|
35
|
-
- Inline controllers are the default for small, single-use controllers. Extract to an external module when the controller grows, is reused, needs separate imports or tests, or drives Canvas 2D, WebGL, or karaoke.
|
|
36
|
-
- The controller is the only executable code in a composition document. Other executable `<script>` elements and inline `on*` handlers are rejected. Libraries are imported as ES modules from the controller.
|
|
48
|
+
- An optional composition controller is declared with `<script type="text/fy-controller">`. It is either inline source or an external module referenced by `src`; a composition has exactly one controller. It may export `mount`, `update`, `dispose`, and `validateProps`; at least one is required. The controller is the only executable code in the document.
|
|
37
49
|
- `fy` is the authoring namespace: `fy-composition`, `fy-transcript`, `data-fy-*`, `--fy-*`, and `text/fy-controller`. `frameyard` remains the product, package, CLI, config, manifest, server-route, import-specifier, and error-code namespace.
|
|
38
|
-
- User controllers are native JavaScript. The framework itself is authored in TypeScript and ships declarations, but 0.
|
|
50
|
+
- User controllers are native JavaScript. The framework itself is authored in TypeScript and ships declarations, but 0.6 does not transpile user TypeScript.
|
|
51
|
+
|
|
52
|
+
### Timeline
|
|
53
|
+
|
|
54
|
+
- A timeline is a versioned JSON document. It references compositions and nested timelines by project ID and media clips by project-relative path.
|
|
55
|
+
- A timeline has a project-fixed format, an ordered list of tracks, and a list of clips. It may declare a `background` color and an optional `durationInFrames`.
|
|
56
|
+
- Tracks are `video` or `audio`. Video tracks composite from bottom to top; audio tracks mix. Each clip belongs to exactly one track. Clips on the same track cannot overlap; clips on different tracks can. Touching endpoints are allowed. Transitions are deferred, so overlap within a track would have ambiguous precedence.
|
|
57
|
+
- A clip has an ID, a track, a source, a timeline start, a source in-point, a duration, and clip-specific presentation settings. Source in-point, duration, and timeline start are integer project frames.
|
|
58
|
+
- Clip sources are:
|
|
59
|
+
- a composition, identified by its project ID;
|
|
60
|
+
- a nested timeline, identified by its project ID;
|
|
61
|
+
- a local video, image, or audio asset.
|
|
62
|
+
- A composition clip fixes props for that instance and may trim the composition's source range. The same composition may appear multiple times with different props, source ranges, transforms, and audio settings.
|
|
63
|
+
- A nested timeline clip is a visual and audio source. It uses the project format, trims with the same source in-point and duration, contributes its audio, and is rendered as a group so parent opacity and transform apply to the whole nested result. Cycles are rejected statically. Timeline clips do not override props of compositions inside the nested timeline in 0.6.
|
|
64
|
+
- Media clips use local project files only. Video and audio durations, dimensions, and audio presence are probed before frame production. Images are static and require an explicit duration. A video or audio clip that exceeds its source range is an error; an omitted duration uses the remaining source.
|
|
65
|
+
- Visual clips support a static transform: fit policy (`contain`, `cover`, `stretch`), an optional explicit `width`/`height` box (both fields together, mutually exclusive with `scale`) or a `scale` multiplier, pixel offset, rotation, and opacity. `fit` applies inside the box; without one, the project frame is the box. No keyframes, blend modes, masks, filters, or other effects in 0.6.
|
|
66
|
+
- Visual clips contribute their audio to the timeline mix unless muted: composition audio, embedded video audio, and nested timeline audio. Audio-only clips live on audio tracks and may source audio or video files. Per-clip and per-audio-track gain and mute are supported. There are no linked A/V pairs; a J/L cut is expressed by muting a video clip and placing a separate audio clip with a different source in-point.
|
|
67
|
+
- A timeline's duration is derived from the latest clip end. An explicit `durationInFrames` may extend it but not cut clips. A timeline with no clips is invalid; an audio-only timeline is valid and renders black video with audio.
|
|
68
|
+
- A timeline background is transparent by default. The final video composites it over black; a nested timeline remains transparent so lower layers can show through. A composition that paints no background is transparent and may be used as an overlay.
|
|
69
|
+
- The preview provides a read-only timeline view: tracks, clips, playhead, program monitor, and diagnostics. It is not a visual editor.
|
|
39
70
|
|
|
40
71
|
## 3. Deterministic execution
|
|
41
72
|
|
|
42
|
-
The
|
|
73
|
+
The timeline frame is the master clock. A composition's frame is derived from the clip's timeline start, source in-point, and duration. The only sources of a composition's animation state remain the integer composition frame and its immutable props.
|
|
43
74
|
|
|
44
|
-
- The runtime owns the frame clock and deterministic randomness.
|
|
45
|
-
- CSS `@keyframes` and Web Animations API animations are paused and positioned from the shared frame clock. `data-fy-anim-*`
|
|
46
|
-
- The runtime sets `--fy-frame`, `--fy-time`, `--fy-progress`, `--fy-fps`, `--fy-duration`, and `--fy-duration-frames` on the composition root every seek.
|
|
75
|
+
- The runtime owns the frame clock and deterministic randomness. A composition controller imports `random("stable:key")` from `frameyard/runtime`.
|
|
76
|
+
- CSS `@keyframes` and Web Animations API animations are paused and positioned from the shared composition frame clock. `data-fy-anim-*` schedules one animation per element in composition frames; the runtime maps frames to milliseconds.
|
|
77
|
+
- The runtime sets `--fy-frame`, `--fy-time`, `--fy-progress`, `--fy-fps`, `--fy-duration`, and `--fy-duration-frames` on the composition root every seek.
|
|
47
78
|
- JavaScript animation runs in the controller's `update()`, which must be synchronous and seek-safe. It cannot depend on previously visited frames.
|
|
48
79
|
- Declarative bindings apply once per load, before the controller mounts. Controller-created DOM is the controller's responsibility.
|
|
49
80
|
- Independent `requestAnimationFrame` loops, timers, CSS transitions, wall-clock reads, and unseeded randomness are not supported animation drivers.
|
|
50
|
-
-
|
|
51
|
-
-
|
|
81
|
+
- Timeline clips use static transforms. Timeline-level animation, transitions, effects, and keyframes are not part of 0.6.
|
|
82
|
+
- Preview and production seek composition clips explicitly. The timeline compositor is deterministic given the captured clip frames, media frames, clip settings, and segment boundaries.
|
|
83
|
+
- Assets, remote data, images, fonts, generated audio, transcripts, and media are resolved before frame production. For a segmented timeline render, each segment's composition and nested-timeline clips are loaded and settled before that segment's frames are captured; no frame production depends on a new network request. Network is blocked during capture.
|
|
52
84
|
- AI model inference is never part of the loading phase, controller lifecycle, or frame production.
|
|
53
85
|
- The baseline supports DOM, CSS, SVG, Canvas 2D, WebGL, and frame-seeked embedded video. Canvas 2D and WebGL are drawn from the current frame by the controller.
|
|
54
|
-
- Embedded video and audio are declared
|
|
86
|
+
- Embedded video and audio inside compositions are declared with `data-fy-*` attributes. The runtime loads local files, pauses them, and seeks video from the frame-derived source time before capture. An unmuted video contributes its audio track to the timeline mix unless the composition opts out or the clip mutes it.
|
|
87
|
+
- Transparent compositions are captured with an alpha-preserving browser background. Without that step, a top-level Chromium capture paints a white canvas and overlays become white rectangles.
|
|
55
88
|
- WebGL 1 and WebGL 2 canvases are captured through the normal screenshot path. Production sessions pin software WebGL so pixel output does not depend on the host GPU.
|
|
56
89
|
- Compositions are trusted local developer code. Frameyard does not claim to render untrusted compositions safely.
|
|
57
90
|
|
|
58
91
|
### Reproducibility guarantee
|
|
59
92
|
|
|
60
|
-
For the same composition revision, props,
|
|
93
|
+
For the same timeline or composition revision, props, assets, segment plan, and frame under a pinned runtime/browser/FFmpeg environment, the captured composition frames and the deterministic timeline composite are identical. The final MP4 is not promised to be bit-identical: encoded bytes depend on the encoder and its runtime.
|
|
61
94
|
|
|
62
|
-
|
|
95
|
+
Preview and production share composition behavior and capture composition frames the same way, but the timeline preview composites layers in Chromium while production composites them with FFmpeg. Small differences in scaling, alpha, and video color conversion are expected and do not violate clip-capture parity.
|
|
63
96
|
|
|
64
97
|
## 4. Preview and production rendering
|
|
65
98
|
|
|
66
|
-
Preview and production execute the same composition
|
|
99
|
+
Preview and production execute the same composition documents and host runtime. They differ in which component drives the frame clock, which compositor combines timeline layers, and whether frames are captured.
|
|
67
100
|
|
|
68
101
|
The preview provides:
|
|
69
102
|
|
|
70
|
-
- Composition selection
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
- Current frame and time display
|
|
74
|
-
- Audio controls
|
|
103
|
+
- Composition preview: composition selection, JSON props editing, play/pause, frame-accurate scrubbing, frame-by-frame stepping with buttons or arrow keys, one-second jumps with buttons or Shift+arrow keys, current frame and time, audio controls, and diagnostics.
|
|
104
|
+
- Timeline preview: timeline selection, a read-only track/clip view, playhead, program monitor, frame-by-frame stepping with buttons or arrow keys, one-second jumps with buttons or Shift+arrow keys, audio controls, and diagnostics.
|
|
105
|
+
- A bounded pool of active composition and nested-timeline clips. It loads clips around the playhead instead of preloading a whole long timeline.
|
|
75
106
|
|
|
76
|
-
It
|
|
107
|
+
The preview server serves each composition HTML document at its project path and injects the framework import map and host runtime. It serves timeline documents and a timeline preview host. The timeline preview host drives active composition/nested-timeline clips, seeks them, and exposes a timeline API to the preview. Preview audio is mixed by the preview page from the resolved timeline audio clips.
|
|
77
108
|
|
|
78
|
-
|
|
109
|
+
Production composition rendering is unchanged: one Chromium session per composition, explicit frame seeks, PNG capture, and FFmpeg encoding.
|
|
79
110
|
|
|
80
|
-
Production rendering:
|
|
111
|
+
Production timeline rendering is segmented and parallel:
|
|
81
112
|
|
|
82
|
-
1.
|
|
83
|
-
2.
|
|
84
|
-
3.
|
|
85
|
-
4.
|
|
86
|
-
5.
|
|
87
|
-
6.
|
|
113
|
+
1. Run static timeline validation and resolve the render plan.
|
|
114
|
+
2. Split the timeline into segments at active-layer changes or a maximum segment duration. Each segment has a fixed set of visual layers and a fixed filter graph.
|
|
115
|
+
3. In parallel workers, capture the active composition and nested-timeline clip frames for each segment with Chromium and encode them to lossless FFV1 intermediates. Transparent clips are captured with an alpha-preserving background.
|
|
116
|
+
4. Decode media clips, apply trims, fit, static transforms, and opacity, composite the segment with FFmpeg, and encode H.264.
|
|
117
|
+
5. Join the ordered segments with a stream copy. Segment boundaries never change frame order or timing.
|
|
118
|
+
6. Mix the timeline audio once with FFmpeg and mux it into the final output.
|
|
119
|
+
7. Publish the output atomically; delete scratch intermediates on success and failure.
|
|
88
120
|
|
|
89
|
-
`
|
|
121
|
+
The default timeline worker count is 8, configurable up to the machine's capacity. Scratch is a configurable directory with a bounded budget; it must not depend on `/tmp` alone. The reference long-form target is a representative 60-minute 1920×1080 30 fps timeline with a 50/50 composition/media split by layer-seconds, 60% one active layer, 30% two, and 10% three, rendered in 30 minutes or less on the reference machine. The 10-second benchmark measured 10.7 s for two composition captures, 35.2 MB of FFV1, and 6.1 s to composite and encode. Continuous three-layer stress runs measured 52.4 s and 58.5 s for 60 s of timeline, about 1× real time, and are documented as worst-case rather than the target workload. The representative gate measured 29.39 s for 60 s with four workers, exact 1800-frame output, and a 1080p media fast path, extrapolating to about 29.4 minutes for 60 minutes. The full 60-minute composition-only gate rendered 108,000 frames in 35.35 minutes with exact 108,000-frame / 3,600 s output; it is stricter than the 50/50 target mix because every frame is an HTML composition capture. The fast path copies full-frame, untransformed video whose source matches the project format and has keyframes at segment boundaries; media that needs scaling or transforms is re-encoded and adds cost not included in that projection.
|
|
90
122
|
|
|
91
|
-
The renderer
|
|
123
|
+
The renderer uses a bounded segment plan, a worker pool, and a scratch budget. It never publishes a partial MP4, and it cleans scratch on success and failure. Segment boundaries preserve timeline frame order and timing; the final audio mix is muxed once.
|
|
124
|
+
|
|
125
|
+
`check` and `still` use the same clip capture and timeline composite path for a requested frame. `check` evaluates every timeline frame; on long timelines this is a validation cost, not a render. `still` captures one frame as PNG without encoding a video.
|
|
92
126
|
|
|
93
127
|
## 5. Audio and output
|
|
94
128
|
|
|
95
|
-
|
|
129
|
+
A timeline has one audio mix. It combines:
|
|
130
|
+
|
|
131
|
+
- composition audio clips declared inside composition clips, shifted and trimmed by the clip's source range;
|
|
132
|
+
- embedded video audio from composition clips and media video clips, unless muted;
|
|
133
|
+
- timeline audio clips on audio tracks;
|
|
134
|
+
- audio from nested timeline clips, recursively.
|
|
135
|
+
|
|
136
|
+
Per-clip gain and mute, per-audio-track gain and mute, and composition-level volume apply. Audio fades are deferred. The mix is produced once with FFmpeg and muxed into the final MP4. Preview mixes the same resolved clips in the browser for monitoring; it is not the production source of truth.
|
|
96
137
|
|
|
97
|
-
Audio, video, and transcript `src` values resolve from the project root. The controller `src` and ordinary HTML asset URLs
|
|
138
|
+
Audio, video, and transcript `src` values resolve from the project root. The controller `src` and ordinary HTML asset URLs resolve relative to the composition document.
|
|
98
139
|
|
|
99
|
-
Generated speech behaves like any other audio clip. Frameyard does not automatically time-stretch it, change
|
|
140
|
+
Generated speech behaves like any other audio clip. Frameyard does not automatically time-stretch it, change timeline duration, or regenerate it to fit. `check` reports clip durations and overrun warnings so users and agents can revise text, timing, or the timeline deliberately.
|
|
100
141
|
|
|
101
|
-
0.
|
|
142
|
+
0.6 produces portable MP4 files with H.264 video and AAC audio. It exposes only a small set of validated encoding options, not arbitrary FFmpeg arguments. Single-frame PNG output through `still` is a debugging artifact, not general image-sequence support.
|
|
102
143
|
|
|
103
|
-
A render fails immediately on an uncaught exception, unhandled rejection, required-asset failure,
|
|
144
|
+
A render fails immediately on an uncaught exception, unhandled rejection, required-asset failure, invalid composition output, segment encoding failure, or scratch failure. Diagnostics identify the timeline, clip, segment, and, where applicable, the frame. The CLI exits nonzero, cleans temporary files, and never reports a partial video as successful. Existing output files are not overwritten unless explicitly requested.
|
|
104
145
|
|
|
105
146
|
## 6. CLI, tooling, and package boundaries
|
|
106
147
|
|
|
107
148
|
Project and composition commands are:
|
|
108
149
|
|
|
109
|
-
- `init`: scaffold a
|
|
110
|
-
- `dev`: start the preview
|
|
111
|
-
- `render <
|
|
112
|
-
- `check <
|
|
113
|
-
- `still <
|
|
114
|
-
- `doctor`: inspect core requirements and optional integrations without repairing or downloading anything
|
|
150
|
+
- `init`: scaffold a timeline-first project with a composition, a one-clip timeline, a project format, an agent guide, a `.gitignore` for `out/`, and a private `package.json` with pinned `dev`, `check`, `render`, and `still` scripts.
|
|
151
|
+
- `dev`: start the preview with composition and timeline modes.
|
|
152
|
+
- `render <id> [--out video.mp4]`: render a timeline or a composition. Timeline renders accept `--workers <n>` and `--scratch <dir>`; composition renders accept `--concurrency <n>` from 1 to 16. The default output is `out/<id>.mp4`.
|
|
153
|
+
- `check <id>`: run static validation, then validate configuration, props, assets, media, audio, and transcript requirements, load the target, and evaluate every frame without capturing or encoding.
|
|
154
|
+
- `still <id> --frame <n>`: capture one requested frame as PNG through the clip capture and timeline composite path.
|
|
155
|
+
- `doctor`: inspect core requirements and optional integrations without repairing or downloading anything.
|
|
115
156
|
|
|
116
|
-
`check`, `still`, and `render` run a Node-side static
|
|
157
|
+
`check`, `still`, and `render` run a Node-side static validation before launching Chromium. For a timeline it validates the JSON document, tracks, clips, references, nested timelines, cycles, frame-rate compatibility, overlaps, source bounds, media, transforms, audio settings, props, and every referenced composition. Static validation and the composition host read the composition grammar through one browser-safe document reader. Timeline diagnostics carry stable codes and optional source locations or JSON paths, and composition diagnostics from inside a timeline carry the clip and track context.
|
|
117
158
|
|
|
118
159
|
Local asset-production commands are `tts` and `transcribe`. Every non-interactive command supports `--json` with stable result and error schemas. Structured results go to stdout; human diagnostics and inference progress go to stderr.
|
|
119
160
|
|
|
120
|
-
The built-in server serves native ES modules
|
|
161
|
+
The built-in server serves native ES modules, static assets, composition entries, timeline documents, and the timeline preview host. It injects an import map and composition host into composition entries and an inline controller through a virtual module URL. It performs no dependency pre-bundling. Third-party libraries must initially be browser-ready ES modules referenced explicitly. Running through the CLI server is required; direct `file://` execution is unsupported for deterministic preview or rendering.
|
|
121
162
|
|
|
122
|
-
Frameyard uses one repository and one publishable npm package with
|
|
163
|
+
Frameyard uses one repository and one publishable npm package with four internal layers:
|
|
123
164
|
|
|
124
|
-
1. Shared composition contracts and HTML
|
|
125
|
-
2. Browser host
|
|
126
|
-
3. Node-based
|
|
165
|
+
1. Shared composition and timeline contracts and HTML/JSON parsing
|
|
166
|
+
2. Browser composition host and timeline preview host
|
|
167
|
+
3. Node-based static validation and segmented timeline renderer
|
|
168
|
+
4. Node-based CLI, asset production, and doctor
|
|
127
169
|
|
|
128
|
-
These layers have clean internal boundaries but no public plugin API. FFmpeg is
|
|
170
|
+
These layers have clean internal boundaries but no public plugin API. FFmpeg is required for encoding, probing, media decoding, audio mixing, and timeline compositing. Skia is not required in 0.6. The project supports the current active Node.js LTS; Linux is the reference and CI platform, while macOS and Windows remain best-effort until covered by real rendering tests.
|
|
129
171
|
|
|
130
172
|
## 7. Official agent skill
|
|
131
173
|
|
|
132
|
-
Frameyard ships an optional, host-neutral agent skill with a `SKILL.md`, supporting references, and thin scripts. The npm package includes skill files matching its API version, and documentation explains host-specific installation or referencing. 0.
|
|
174
|
+
Frameyard ships an optional, host-neutral agent skill with a `SKILL.md`, supporting references, and thin scripts. The npm package includes skill files matching its API version, and documentation explains host-specific installation or referencing. 0.6 does not add a skill-installer command.
|
|
133
175
|
|
|
134
176
|
The skill:
|
|
135
177
|
|
|
136
|
-
- Uses the normal project format, HTML composition contract, optional controller, and CLI available to humans.
|
|
178
|
+
- Uses the normal project format, HTML composition contract, JSON timeline contract, optional controller, and CLI available to humans.
|
|
137
179
|
- Does not introduce an agent-only runtime, MCP server, hosted control plane, or separate rendering API.
|
|
138
180
|
- Triggers for Frameyard authoring and operation rather than claiming to be a general-purpose media-generation skill.
|
|
139
181
|
- Uses Frameyard's audio wrappers instead of invoking `qwen-tts` or `whisper-cli` directly.
|
|
140
|
-
- Includes references for deterministic HTML authoring,
|
|
182
|
+
- Includes references for deterministic HTML authoring, timeline JSON authoring, tracks, clips, source ranges, props, media, nested timelines, static transforms, audio, validation, diagnostics, common mistakes, subtitle and karaoke recipes, JSON command results, long-form worker/scratch settings, and failure recovery.
|
|
141
183
|
- Invokes speech synthesis or transcription only when requested or explicitly approved as part of the brief.
|
|
142
184
|
- Does not overwrite or regenerate existing generated assets without permission.
|
|
143
185
|
- Runs `check`, inspects representative `still` images when the host supports image viewing, and discloses when visual inspection was impossible.
|
|
144
186
|
- Does not claim success when checks fail or rendering is partial.
|
|
145
187
|
|
|
146
|
-
A successful agent workflow preserves and reports the source project, props, generated assets, provenance manifest, validation results, and final video path. The user must be able to inspect, modify, and reproduce the result rather than receiving only an opaque MP4.
|
|
188
|
+
A successful agent workflow preserves and reports the source project, timeline document, props, generated assets, provenance manifest, validation results, and final video path. The user must be able to inspect, modify, and reproduce the result rather than receiving only an opaque MP4.
|
|
147
189
|
|
|
148
190
|
## 8. Local speech synthesis
|
|
149
191
|
|
|
150
192
|
The `tts` command integrates [`qwentts.cpp`](https://github.com/ServeurpersoCom/qwentts.cpp) through its external `qwen-tts` executable. It does not link the native library or require the upstream server.
|
|
151
193
|
|
|
152
|
-
0.
|
|
194
|
+
0.6 supports CustomVoice mode only:
|
|
153
195
|
|
|
154
196
|
- A named speaker is required.
|
|
155
197
|
- An optional style instruction and language may be supplied.
|
|
@@ -175,7 +217,7 @@ The canonical artifact is a versioned Frameyard JSON document containing:
|
|
|
175
217
|
- Timed segments
|
|
176
218
|
- Optional word timings
|
|
177
219
|
|
|
178
|
-
All timestamps are integer milliseconds relative to the source audio, not composition frame numbers.
|
|
220
|
+
All timestamps are integer milliseconds relative to the source audio, not timeline or composition frame numbers. A controller converts them using the audio clip's start frame, source trim, and the composition frame rate.
|
|
179
221
|
|
|
180
222
|
Compositions declare required transcript assets with `<fy-transcript>` elements:
|
|
181
223
|
|
|
@@ -187,11 +229,11 @@ Compositions declare required transcript assets with `<fy-transcript>` elements:
|
|
|
187
229
|
|
|
188
230
|
SRT and VTT are derived exports, not the canonical contract. Word-level karaoke requires actual word timings and fails validation when they are unavailable. Frameyard never fabricates word timings by interpolating segment timestamps and never executes Whisper's generated bash/FFmpeg karaoke script.
|
|
189
231
|
|
|
190
|
-
The official skill documents seek-safe subtitle and karaoke recipes. Compositions retain responsibility for visual presentation; 0.
|
|
232
|
+
The official skill documents seek-safe subtitle and karaoke recipes. Compositions retain responsibility for visual presentation; 0.6 has no built-in subtitle renderer and does not automatically burn captions into videos. Karaoke presentation uses the optional controller.
|
|
191
233
|
|
|
192
234
|
## 10. Generated assets and inference operation
|
|
193
235
|
|
|
194
|
-
Speech synthesis and transcription are separate asset-production operations that complete before composition
|
|
236
|
+
Speech synthesis and transcription are separate asset-production operations that complete before a timeline or composition is loaded or rendered. Their outputs are ordinary local project assets. Once those assets are frozen, ordinary authoring, preview, checking, and rendering require neither AI executable nor model.
|
|
195
237
|
|
|
196
238
|
Both integrations are optional and local-only, with no cloud fallback. Network activity needed to acquire tools or models is a separate explicit setup operation, never a hidden side effect of generation or rendering.
|
|
197
239
|
|
|
@@ -214,19 +256,21 @@ Tests prioritize public behavior and end-to-end evidence over implementation-onl
|
|
|
214
256
|
|
|
215
257
|
- HTML compositions validate metadata, default props, bindings, conditionals, repeats, and controller declarations, including inline/external parity and the exactly-one-controller rule.
|
|
216
258
|
- Static composition validation catches metadata, root/controller count, binding, animation, script, element, and asset-reference errors before Chromium.
|
|
217
|
-
-
|
|
218
|
-
-
|
|
219
|
-
-
|
|
220
|
-
-
|
|
221
|
-
-
|
|
259
|
+
- Timeline JSON validation catches schema, track, clip, reference, cycle, frame-rate, overlap, bounds, media, transform, audio, and props errors before Chromium.
|
|
260
|
+
- Diagnostics carry stable codes and source locations or JSON paths; JSON results expose the composition or timeline entry, clips, tracks, and top-level diagnostics.
|
|
261
|
+
- Sequential, individual, random-order, and parallel composition renders produce equivalent images; timeline segment workers produce ordered output and identical captured composition frames.
|
|
262
|
+
- Determinism checks compare captured composition pixels or stills. The final H.264 bytes and the FFmpeg composite versus Chromium preview are not reproducibility oracles.
|
|
263
|
+
- Preview and renderer use the same composition document and host behavior; timeline preview uses the same active clip hosts.
|
|
264
|
+
- CSS, controller JavaScript, SVG, Canvas, WebGL, embedded video, and audio frames seek correctly.
|
|
222
265
|
- Frame-scheduled `data-fy-anim-*` animations and frame-state CSS variables produce the expected frames.
|
|
223
|
-
-
|
|
224
|
-
-
|
|
225
|
-
-
|
|
226
|
-
-
|
|
227
|
-
-
|
|
228
|
-
-
|
|
229
|
-
-
|
|
266
|
+
- Timeline capture preserves alpha for transparent compositions; FFV1 intermediates decode pixel-identically to the captured frames.
|
|
267
|
+
- Timeline segment encoding, ordered concatenation, global audio mix, and scratch cleanup produce the expected MP4 dimensions, frame count, duration, and audio stream.
|
|
268
|
+
- Nested timelines preserve group opacity and transform semantics; cycles fail static validation.
|
|
269
|
+
- Media clips trim and fit deterministically; images require durations; source overruns fail.
|
|
270
|
+
- Props overrides for timeline composition clips merge over clip props and are reflected in the render.
|
|
271
|
+
- `check` exercises every frame; `still` follows the clip capture and timeline composite path.
|
|
272
|
+
- The 10-second and 60-second long-form benchmarks record capture, FFV1, composite, encode, disk, worker, and audio numbers. Continuous three-layer runs measured 52.4 s and 58.5 s for 60 s of timeline and are documented as worst-case (~1× real time). The representative 50/50, 60/30/10 occupancy gate measured 29.39 s for 60 s with four workers and a 1080p media fast path, extrapolating to about 29.4 minutes for 60 minutes with exact 1800-frame output. The full 60-minute composition-only gate rendered 108,000 frames in 35.35 minutes with exact output and clean scratch, documenting composition-heavy performance above 30 minutes.
|
|
273
|
+
- Golden-frame tests cover representative composition and timeline visual behavior.
|
|
230
274
|
- Normal CI uses fake `qwen-tts` and `whisper-cli` executables and small fixtures to verify arguments, artifacts, manifests, cancellation, and errors without model downloads or GPU hardware.
|
|
231
275
|
- Real-model integration tests are explicitly opt-in and use documented upstream revisions.
|
|
232
276
|
- Agent-workflow evaluations verify source preservation, provenance, validation, still inspection behavior, failure reporting, and final renders.
|
|
@@ -235,7 +279,14 @@ Tests prioritize public behavior and end-to-end evidence over implementation-onl
|
|
|
235
279
|
|
|
236
280
|
These are scope boundaries, not permanent rejections:
|
|
237
281
|
|
|
238
|
-
-
|
|
282
|
+
- Transitions, effects, keyframes, blend modes, masks, and audio fades
|
|
283
|
+
- Full visual timeline editing, drag-and-drop, clip handles, and undo/redo
|
|
284
|
+
- Timeline-level variables and prop overrides for compositions inside nested timelines
|
|
285
|
+
- Track solo and video-track visibility
|
|
286
|
+
- Per-timeline formats and frame-rate conversion/retiming
|
|
287
|
+
- Persistent clip caches; the segmented renderer cleans its intermediates
|
|
288
|
+
- Hardware encoders, GPU compositing, and non-H.264 output
|
|
289
|
+
- Hosted rendering, collaboration, and asset marketplaces
|
|
239
290
|
- Cloud generative-AI services, text-to-video generation, and image generation
|
|
240
291
|
- `qwentts.cpp` reference-audio voice cloning and VoiceDesign
|
|
241
292
|
- Automatic long-text chunking, streaming speech synthesis, and alternative generated-audio formats
|
|
@@ -247,17 +298,16 @@ These are scope boundaries, not permanent rejections:
|
|
|
247
298
|
- Agent-only runtimes, MCP servers, hosted agent control planes, and host-specific skill installers
|
|
248
299
|
- React or other UI-framework adapters in the core
|
|
249
300
|
- Public plugin APIs and a broad integration ecosystem
|
|
250
|
-
- Dynamic composition metadata derived from props
|
|
301
|
+
- Dynamic composition or timeline metadata derived from props
|
|
251
302
|
- Live streams, remote media, and other visual sources that cannot be deterministically seeked
|
|
252
303
|
- Dynamic per-frame asset loading or AI inference
|
|
253
|
-
- Frame caches
|
|
254
304
|
- Batch still capture; agents can run `still` once per representative frame
|
|
255
305
|
- Additional final-video formats, general image-sequence output, and arbitrary FFmpeg argument passthrough
|
|
256
306
|
- Built-in TypeScript transpilation and npm dependency optimization
|
|
257
307
|
- Rendering untrusted compositions
|
|
258
308
|
- Bit-identical cross-platform encoded output or AI regeneration
|
|
259
|
-
- A minimum production rendering-speed guarantee
|
|
309
|
+
- A minimum production rendering-speed guarantee for compositions or timelines
|
|
260
310
|
|
|
261
311
|
## 13. Release posture
|
|
262
312
|
|
|
263
|
-
Frameyard is MIT-licensed. Initial releases use `0.x` versioning, and composition, configuration, CLI, JSON-result, transcript, and skill-contract changes are documented explicitly until those contracts stabilize. 0.
|
|
313
|
+
Frameyard is MIT-licensed. Initial releases use `0.x` versioning, and composition, timeline, configuration, CLI, JSON-result, transcript, and skill-contract changes are documented explicitly until those contracts stabilize. 0.6.0 adds timelines, project formats, segmented timeline rendering, and a timeline-first scaffold without breaking the existing HTML composition authoring contract. See [ADR 0010](./adr/0010-make-timelines-the-render-unit.md), [ADR 0011](./adr/0011-compose-timeline-frames-in-a-live-browser-host.md), and [ADR 0012](./adr/0012-render-timelines-with-segmented-lossless-clip-intermediates.md).
|
package/examples/demo/README.md
CHANGED
|
@@ -10,15 +10,22 @@ A 30-second, 1920×1080 HTML composition that exercises the current core:
|
|
|
10
10
|
- frame-state CSS variables for the progress bar
|
|
11
11
|
|
|
12
12
|
The composition lives in `compositions/demo.html`; the optional controller is
|
|
13
|
-
`compositions/demo.controller.js`.
|
|
13
|
+
`compositions/demo.controller.js`. `timelines/demo.timeline.json` wraps the
|
|
14
|
+
composition as a clip in a 1920×1080, 30 fps timeline.
|
|
14
15
|
|
|
15
16
|
From the repository root:
|
|
16
17
|
|
|
17
18
|
```sh
|
|
18
19
|
pnpm build
|
|
19
|
-
node dist/cli.js check demo --project examples/demo
|
|
20
|
-
node dist/cli.js still demo --frame 240 --project examples/demo --out demo-still.png
|
|
21
|
-
node dist/cli.js render demo --project examples/demo --props examples/demo/props/demo.json
|
|
20
|
+
node dist/cli.js check demo-timeline --project examples/demo
|
|
21
|
+
node dist/cli.js still demo-timeline --frame 240 --project examples/demo --out demo-still.png
|
|
22
|
+
node dist/cli.js render demo-timeline --project examples/demo --props examples/demo/props/demo.json
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The composition remains renderable on its own:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
node dist/cli.js render demo --project examples/demo --props examples/demo/props/demo.json
|
|
22
29
|
```
|
|
23
30
|
|
|
24
31
|
Start the interactive preview with:
|