frameyard 0.9.0 → 0.10.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 +67 -0
- package/README.md +1 -1
- package/dist/preview/fonts/LICENSE-figtree.txt +93 -0
- package/dist/preview/fonts/LICENSE-space-mono.txt +93 -0
- package/dist/preview/fonts/README.md +23 -0
- package/dist/preview/fonts/figtree-latin-wght-normal.woff2 +0 -0
- package/dist/preview/fonts/space-mono-latin-400-normal.woff2 +0 -0
- package/dist/preview/fonts/space-mono-latin-700-normal.woff2 +0 -0
- package/dist/preview/main.js +5 -2
- package/dist/preview/main.js.map +1 -1
- package/dist/preview/timeline-main.js +41 -23
- package/dist/preview/timeline-main.js.map +1 -1
- package/dist/renderer/audio.d.ts +6 -0
- package/dist/renderer/audio.d.ts.map +1 -1
- package/dist/renderer/audio.js +3 -1
- package/dist/renderer/audio.js.map +1 -1
- package/dist/renderer/browser.d.ts.map +1 -1
- package/dist/renderer/browser.js +13 -0
- package/dist/renderer/browser.js.map +1 -1
- package/dist/renderer/concurrency.d.ts +6 -0
- package/dist/renderer/concurrency.d.ts.map +1 -0
- package/dist/renderer/concurrency.js +27 -0
- package/dist/renderer/concurrency.js.map +1 -0
- package/dist/renderer/ffmpeg.d.ts +62 -3
- package/dist/renderer/ffmpeg.d.ts.map +1 -1
- package/dist/renderer/ffmpeg.js +326 -45
- package/dist/renderer/ffmpeg.js.map +1 -1
- package/dist/renderer/session-pool.d.ts +28 -0
- package/dist/renderer/session-pool.d.ts.map +1 -0
- package/dist/renderer/session-pool.js +91 -0
- package/dist/renderer/session-pool.js.map +1 -0
- package/dist/renderer/timeline.d.ts.map +1 -1
- package/dist/renderer/timeline.js +518 -38
- package/dist/renderer/timeline.js.map +1 -1
- package/dist/renderer/timings.d.ts +13 -0
- package/dist/renderer/timings.d.ts.map +1 -0
- package/dist/renderer/timings.js +29 -0
- package/dist/renderer/timings.js.map +1 -0
- package/dist/server/preview-html.d.ts.map +1 -1
- package/dist/server/preview-html.js +74 -188
- package/dist/server/preview-html.js.map +1 -1
- package/dist/server/preview-style.d.ts +11 -0
- package/dist/server/preview-style.d.ts.map +1 -0
- package/dist/server/preview-style.js +298 -0
- package/dist/server/preview-style.js.map +1 -0
- package/dist/server/timeline-preview-html.d.ts.map +1 -1
- package/dist/server/timeline-preview-html.js +140 -164
- package/dist/server/timeline-preview-html.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/docs/adr/0012-render-timelines-with-segmented-lossless-clip-intermediates.md +1 -1
- package/docs/adr/0024-stream-composition-captures-and-skip-trivial-composites.md +86 -0
- package/docs/adr/0025-capture-timeline-layers-in-parallel-with-a-global-limit.md +67 -0
- package/docs/adr/0026-reuse-loaded-composition-sessions-across-segments.md +70 -0
- package/docs/adr/0027-encode-two-full-frame-layers-through-dual-pipes.md +76 -0
- package/docs/adr/0028-encode-full-frame-video-segments-directly.md +65 -0
- package/docs/preview-testing.md +8 -0
- package/docs/v0.x-design.md +3 -3
- package/package.json +2 -2
- package/skills/frameyard/SKILL.md +1 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Encode a full-frame composition and a static overlay through dual pipes
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted. Extends [ADR-0026](./0026-reuse-loaded-composition-sessions-across-segments.md).
|
|
4
|
+
**Date:** 2026-11-06
|
|
5
|
+
|
|
6
|
+
A segment with a full-frame composition base and one static composition overlay
|
|
7
|
+
now captures both layers concurrently and feeds them to one FFmpeg process
|
|
8
|
+
through two image pipes. The base has an identity transform; the overlay may use
|
|
9
|
+
a static fit, box, and position, but no keyframes, blend, transition, or
|
|
10
|
+
opacity. The process composites the background, base, and overlay and encodes
|
|
11
|
+
the delivery segment directly. The FFV1 intermediates and the separate
|
|
12
|
+
composite pass are skipped.
|
|
13
|
+
|
|
14
|
+
## Context
|
|
15
|
+
|
|
16
|
+
The two-layer 60-second PIP gate takes 43.78 s; the overlay is a 640×360
|
|
17
|
+
composition on a second track. A two-full-frame-layer workload (1920×1080 base
|
|
18
|
+
plus a 1920×1080 transparent overlay) took 53.27 s with the normal FFV1 and
|
|
19
|
+
composite path. Both captures already ran concurrently after ADR 0025, but the
|
|
20
|
+
segment still paid for two FFV1 encodes, two decodes, and a separate composite
|
|
21
|
+
encode.
|
|
22
|
+
|
|
23
|
+
FFmpeg can read a second image stream from `pipe:3`, and Node can provide that
|
|
24
|
+
extra stdio pipe on Linux and macOS. The two captures write to independent
|
|
25
|
+
pipes, so neither blocks the other while FFmpeg overlays frames in order.
|
|
26
|
+
|
|
27
|
+
## Decision
|
|
28
|
+
|
|
29
|
+
- `startDualPipeSegmentEncoder` spawns one FFmpeg process with:
|
|
30
|
+
- `pipe:0` for the base composition;
|
|
31
|
+
- `pipe:3` for the overlay composition;
|
|
32
|
+
- a `lavfi color` input for the timeline background;
|
|
33
|
+
- `[2:v][0:v]overlay`, then `[base][1:v]overlay`, then the delivery encoder.
|
|
34
|
+
- `captureTwoLayerDirectComposition` leases two capture sessions, writes each
|
|
35
|
+
layer to its pipe, and waits for both frame counts before finishing.
|
|
36
|
+
- The fast path requires exactly two composition layers: a base that matches the
|
|
37
|
+
stage with an identity transform, and an overlay with no keyframes, blend,
|
|
38
|
+
transition, opacity, scale, or rotation. The overlay may use a static fit,
|
|
39
|
+
explicit box, and position. An opaque timeline background is required.
|
|
40
|
+
- Windows falls back to the FFV1 and composite path because extra stdio pipe
|
|
41
|
+
descriptors are not portable there.
|
|
42
|
+
- `FRAMEYARD_DISABLE_DUAL_PIPE=1` forces the fallback for A/B measurements.
|
|
43
|
+
- One-layer direct segments keep `startDirectSegmentEncoder`; PIP, transformed,
|
|
44
|
+
blended, keyframed, nested, static, and media layers keep the segmented
|
|
45
|
+
lossless path.
|
|
46
|
+
|
|
47
|
+
## Considered Options
|
|
48
|
+
|
|
49
|
+
- **General multi-pipe compositor for any layer count.** Rejected for now:
|
|
50
|
+
extra pipes multiply the coordination surface and make Windows support
|
|
51
|
+
harder. Two full-frame layers cover the measured multi-layer case.
|
|
52
|
+
- **Interleave two captures into one pipe.** Rejected: the filter graph would
|
|
53
|
+
need frame-splitting metadata and the capture loops would have to lockstep.
|
|
54
|
+
- **Buffer the base layer and stream only the overlay.** Rejected: buffering a
|
|
55
|
+
300-frame 1080p layer costs hundreds of megabytes and adds a copy.
|
|
56
|
+
- **Keep FFV1 and tune the composite.** Measured filters and thread knobs gave
|
|
57
|
+
no meaningful gain; the intermediate round trip is the cost.
|
|
58
|
+
|
|
59
|
+
## Consequences
|
|
60
|
+
|
|
61
|
+
- The two-full-frame-layer 60-second gate fell from 53.27 s to 34.62 s (−35.0%)
|
|
62
|
+
with byte-identical output. The full 60-minute two-layer gate completed in
|
|
63
|
+
29.69 minutes with eight workers, 108,000 exact frames, and clean scratch,
|
|
64
|
+
just inside the 30-minute target.
|
|
65
|
+
- The two-layer PIP 60-second gate fell from 43.78 s to 33.90 s (−22.6%); sampled
|
|
66
|
+
decoded frames are pixel-identical to the FFV1-and-composite path. The full
|
|
67
|
+
PIP 60-minute gate completed in 25.75 minutes with eight workers, 108,000
|
|
68
|
+
exact frames, and clean scratch.
|
|
69
|
+
- The fast path writes no FFV1 files and no PNG sequences for qualifying
|
|
70
|
+
segments.
|
|
71
|
+
- A dual-pipe failure aborts both FFmpeg inputs and discards both sessions;
|
|
72
|
+
frame counts are checked per layer before publication.
|
|
73
|
+
- Windows and non-qualifying segments keep the existing deterministic path, so
|
|
74
|
+
the capture-pixel guarantee is unchanged.
|
|
75
|
+
- Tests cover two full-frame compositions with a transparent overlay over a
|
|
76
|
+
non-black background, plus the full timeline rendering suite.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Encode full-frame video segments directly
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted. Extends [ADR-0027](./0027-encode-two-full-frame-layers-through-dual-pipes.md).
|
|
4
|
+
**Date:** 2026-11-06
|
|
5
|
+
|
|
6
|
+
A segment with one full-frame video layer, an identity transform, and an opaque
|
|
7
|
+
timeline background now decodes and re-encodes the source range directly into
|
|
8
|
+
the delivery segment. It skips the background overlay, fit, presentation, and
|
|
9
|
+
composite filter graph, but keeps the same delivery encoder and container as
|
|
10
|
+
every other segment.
|
|
11
|
+
|
|
12
|
+
## Context
|
|
13
|
+
|
|
14
|
+
The representative 60-minute 50/50 gate contains 24 seconds per minute of
|
|
15
|
+
full-frame video on a single track. The composite path still built a color
|
|
16
|
+
background, overlaid the video, normalized timestamps, fitted the frame, and
|
|
17
|
+
then encoded. The video source already matches the stage, so those filters are
|
|
18
|
+
identity work except for the fps/format normalization.
|
|
19
|
+
|
|
20
|
+
Stream-copy was considered and deferred: it requires keyframe alignment, matching
|
|
21
|
+
codec parameters, and a concat-compatible bitstream across composition and media
|
|
22
|
+
segments. A direct re-encode avoids those risks while removing the composite
|
|
23
|
+
overhead.
|
|
24
|
+
|
|
25
|
+
## Decision
|
|
26
|
+
|
|
27
|
+
- `encodeVideoSegmentDirect` seeks to the clip's source start, maps the first
|
|
28
|
+
video stream, drops audio, applies
|
|
29
|
+
`fps=<project fps>,format=rgba,format=yuv420p`, and encodes with the normal
|
|
30
|
+
delivery encoder/container settings. The RGBA round trip preserves the
|
|
31
|
+
composite path's color conversion and keeps decoded pixels identical.
|
|
32
|
+
- The fast path requires one visual layer whose source is a video matching the
|
|
33
|
+
stage dimensions, an identity transform, and no keyframes, blend, transition,
|
|
34
|
+
or opacity. The timeline background must be opaque.
|
|
35
|
+
- `FRAMEYARD_DISABLE_VIDEO_DIRECT=1` forces the composite path for A/B
|
|
36
|
+
measurements.
|
|
37
|
+
- Video with transforms, opacity, overlays, keyframes, transitions, or a
|
|
38
|
+
non-matching source/stage size keeps the composite path. Composition and
|
|
39
|
+
nested-timeline segments are unaffected.
|
|
40
|
+
|
|
41
|
+
## Considered Options
|
|
42
|
+
|
|
43
|
+
- **Stream-copy the video range.** Deferred: keyframe alignment and mixed-codec
|
|
44
|
+
concat compatibility need a larger probe and validation surface. A direct
|
|
45
|
+
re-encode reaches the target without that risk.
|
|
46
|
+
- **Keep the composite graph.** Rejected for this case: the background, fit, and
|
|
47
|
+
presentation filters are identity work for a full-frame video.
|
|
48
|
+
- **Use the dual-pipe path.** Not applicable: there is only one visual layer.
|
|
49
|
+
|
|
50
|
+
## Consequences
|
|
51
|
+
|
|
52
|
+
- Full-frame video segments still re-encode, so every delivered segment shares
|
|
53
|
+
the same codec, profile, and container settings. The conformance risk is lower
|
|
54
|
+
than stream-copy.
|
|
55
|
+
- The representative 60-minute 50/50 gate drops the composite path for its
|
|
56
|
+
single-video seconds while retaining it for overlays, PIP, images, and
|
|
57
|
+
multi-layer segments.
|
|
58
|
+
- A 60-second full-frame video-only gate fell from 10.65 s to 7.61 s (−28.5%)
|
|
59
|
+
with pixel-identical decoded frames.
|
|
60
|
+
- The representative 60-minute 50/50 gate fell from 16.82 to 15.57 minutes
|
|
61
|
+
(−7.4%) with 180 direct video segments, exact 108,000 frames, clean scratch,
|
|
62
|
+
and a byte-identical output file.
|
|
63
|
+
- Tests cover a full-frame video timeline through the direct path and the
|
|
64
|
+
existing media/blend/keyframe/timeline suites.
|
|
65
|
+
- The fast path is internal; there is no CLI or JSON contract change.
|
package/docs/preview-testing.md
CHANGED
|
@@ -39,6 +39,14 @@ expose the same seek/settle contract the renderer uses.
|
|
|
39
39
|
`opacity` is `clipOpacity × eased progress` and it stacks above the outgoing
|
|
40
40
|
layer on the same track. The strip draws a `.transition` band with a
|
|
41
41
|
`from → to` tooltip; it is read-only.
|
|
42
|
+
- The strip opens with a `.ruler-scale` carrying five `.ruler-tick` labels at
|
|
43
|
+
0/25/50/75/100% of the frame range. One `.playhead` line spans the ruler and
|
|
44
|
+
every track, driven by a `--playhead-factor` custom property on
|
|
45
|
+
`#timeline-inner`; `--progress` on `#scrub` fills the transport rail.
|
|
46
|
+
- Both preview pages share the chrome in `src/server/preview-style.ts` and its
|
|
47
|
+
design tokens. The chrome serves its own Figtree and Space Mono from
|
|
48
|
+
`/__frameyard/framework/preview/fonts/` and does not link the project font
|
|
49
|
+
sheet. The embedded host page has none of this chrome.
|
|
42
50
|
|
|
43
51
|
## Waiting for a frame
|
|
44
52
|
|
package/docs/v0.x-design.md
CHANGED
|
@@ -118,13 +118,13 @@ Production timeline rendering is segmented and parallel:
|
|
|
118
118
|
|
|
119
119
|
1. Run static timeline validation, resolve the timeline, and project the scene and render plan.
|
|
120
120
|
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.
|
|
121
|
-
3. In parallel workers, capture the active composition and nested-timeline clip frames for each segment with Chromium and
|
|
121
|
+
3. In parallel workers, capture the active composition and nested-timeline clip frames for each segment with Chromium and stream them into lossless FFV1 intermediates. Independent layers of one segment are captured concurrently under a global FIFO session limit, and loaded composition sessions are reused across segments when their entry, props, and transparency match. Transparent clips are captured with an alpha-preserving background. A static composition is captured once per props variant as a transparent PNG and reused as an image layer across segments and workers. A segment with one full-frame, untransformed composition and no keyframes, blend, transition, or opacity skips the FFV1 intermediate and the composite, encoding the capture directly into the delivery segment over the timeline background. A full-frame composition base plus a static composition overlay (including a static PIP box) uses two image pipes into one FFmpeg process, which composites the background, base, and scaled overlay before the delivery encode; Windows keeps the segmented fallback. A single full-frame video with an identity transform re-encodes its source range directly, skipping the composite filter graph while keeping the delivery encoder settings.
|
|
122
122
|
4. Decode media clips, apply trims, fit, presentation keyframes, rotation into an expanded bound, and opacity, composite the segment with FFmpeg, and encode H.264, HEVC, or VP9.
|
|
123
123
|
5. Join the ordered segments with a stream copy. Segment boundaries never change frame order or timing.
|
|
124
124
|
6. Mix the timeline audio once with FFmpeg and mux it into the final output.
|
|
125
125
|
7. Publish the output atomically; delete scratch intermediates on success and failure.
|
|
126
126
|
|
|
127
|
-
The default timeline worker count is 8, configurable up to the machine's capacity. With `--encoder nvenc` the count is capped at eight concurrent encode sessions, the consumer driver limit; a larger `--workers` value produces an `ENCODER_WARNING` and the lower count. 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
|
|
127
|
+
The default timeline worker count is 8, configurable up to the machine's capacity. With `--encoder nvenc` the count is capped at eight concurrent encode sessions, the consumer driver limit; a larger `--workers` value produces an `ENCODER_WARNING` and the lower count. 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 37.28 minutes with four workers; it is stricter than the 50/50 target mix because every frame is an HTML composition capture. Capture was 48.9% of worker time, FFV1 23.2%, composite 24.7%, and session setup 2.8%. Composition captures now stream PNG buffers into FFV1, and a segment with one full-frame, untransformed composition skips the intermediate and composite. The 60-second one-layer gate fell from 43.27 s to 27.64 s, and the full 60-minute gate completed in 19.83 minutes with eight workers; the direct output was byte-identical to the FFV1-and-composite output. Reusing loaded sessions reduced the 60-minute gate further to 18.78 minutes with eight sessions instead of 360. The two-layer PIP 60-second gate improved from 62.79 s to 59.60 s with streaming and to 43.78 s with parallel layer capture under a global session limit. A full-frame composition base plus a static composition overlay uses dual image pipes; the full-frame 60-second workload fell from 53.27 s to 34.62 s, the PIP 60-second workload from 43.78 s to 33.90 s, and the full two-layer 60-minute gates completed in 29.69 minutes (full-frame) and 25.75 minutes (PIP) with eight workers. The production representative 60-minute gate — 50/50 layer-seconds, 60/30/10 occupancy, 360 clips, 540 segments, and video re-encoded rather than stream-copied — completed in 16.82 minutes with eight workers, exact 108,000 frames, and clean scratch. Direct full-frame video re-encoding later reduced it to 15.57 minutes with a byte-identical file; a 60-second video-only gate fell from 10.65 to 7.61 seconds. The 10-minute one-layer gate improved from 211.8 s to 192.6 s by reusing loaded composition sessions across segments. The fast path copies full-frame, untransformed video whose source matches the project format and whose source keyframes (I-frames) fall on segment boundaries; media that needs scaling or transforms is re-encoded and adds cost not included in that projection. Timeline clip keyframes add per-frame filter expressions and, for animated opacity or scale, an alpha-mask pass per affected layer; the keyframe benchmark reports current timings and is not part of the 60-minute projection.
|
|
128
128
|
|
|
129
129
|
The renderer uses a bounded segment plan, a worker pool, and a scratch budget. It never publishes a partial output, and it cleans scratch on success and failure. Segment boundaries preserve timeline frame order and timing; the final audio mix is muxed once.
|
|
130
130
|
|
|
@@ -296,7 +296,7 @@ Tests prioritize public behavior and end-to-end evidence over implementation-onl
|
|
|
296
296
|
- Media clips trim and fit deterministically; images require durations; source overruns fail.
|
|
297
297
|
- Props overrides for timeline composition clips merge over clip props and are reflected in the render.
|
|
298
298
|
- `check` exercises every animated frame and inspects a static composition once; it also evaluates every keyframe channel at every timeline frame. `still` follows the clip capture and timeline composite path. A static composition render captures one PNG; a timeline reuses one static image capture per props variant.
|
|
299
|
-
- 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
|
|
299
|
+
- 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 37.28 minutes with four workers before streaming and the direct-segment fast path; the same gate completed in 19.83 minutes with eight workers after ADR 0024 and 18.78 minutes after session reuse (ADR 0026), with exact output, clean scratch, and a byte-identical file. The ten-minute gate projects about 24 minutes at four workers. Independent layers are captured concurrently under a global session limit (ADR 0025); the two-layer PIP 60-second gate fell from 59.60 s to 43.78 s with parallel captures. A full-frame composition base plus a static composition overlay encodes through dual image pipes (ADR 0027); the full-frame 60-second workload fell from 53.27 s to 34.62 s, the PIP 60-second workload from 43.78 s to 33.90 s, and the full two-layer 60-minute gates completed in 29.69 minutes (full-frame) and 25.75 minutes (PIP) with eight workers. The representative 60-minute 50/50 production gate completed in 16.82 minutes with eight workers, exact 108,000 frames, clean scratch, and no video stream-copy; direct full-frame video re-encoding reduced it to 15.57 minutes with a byte-identical file. Loaded composition sessions are reused across segments (ADR 0026); the 10-minute one-layer gate fell from 211.8 s to 192.6 s, and the full gate opened eight sessions instead of 360.
|
|
300
300
|
- Golden-frame tests cover representative composition and timeline visual behavior.
|
|
301
301
|
- Normal CI uses fake `qwen-tts`, `sherpa-onnx-offline-tts`, and `whisper-cli` executables and small fixtures to verify arguments, artifacts, manifests, cancellation, and errors without model downloads or GPU hardware.
|
|
302
302
|
- Real-model integration tests are explicitly opt-in and use documented upstream revisions.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frameyard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Local-first, deterministic video composition framework for HTML, CSS, and JavaScript.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"vitest": "5.0.5"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
|
-
"build": "tsc -p tsconfig.json",
|
|
67
|
+
"build": "tsc -p tsconfig.json && node scripts/copy-preview-fonts.mjs",
|
|
68
68
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
69
69
|
"typecheck:test": "tsc -p tsconfig.test.json",
|
|
70
70
|
"typecheck:browser": "tsc -p tsconfig.browser.json",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: frameyard
|
|
3
3
|
description: Create, validate, inspect, and render deterministic Frameyard videos authored with HTML compositions and JSON timelines. Use when a user asks to build or operate a Frameyard project, produce parameterized video, assemble clips into a timeline, search or install project fonts, add a local TTS or transcription asset through Frameyard's wrappers, or diagnose a Frameyard render. Do not use for general-purpose media generation outside a Frameyard project.
|
|
4
|
-
frameyard-api-version: 0.
|
|
4
|
+
frameyard-api-version: 0.10.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Frameyard
|