frameyard 0.8.0 → 0.9.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 +110 -14
- package/GLOSSARY.md +112 -2
- package/README.md +302 -265
- package/dist/assets/integrations.d.ts +8 -4
- package/dist/assets/integrations.d.ts.map +1 -1
- package/dist/assets/integrations.js +8 -4
- package/dist/assets/integrations.js.map +1 -1
- package/dist/assets/provenance.d.ts +2 -2
- package/dist/assets/provenance.d.ts.map +1 -1
- package/dist/assets/provenance.js +5 -3
- package/dist/assets/provenance.js.map +1 -1
- package/dist/assets/tts-supertonic.d.ts +28 -0
- package/dist/assets/tts-supertonic.d.ts.map +1 -0
- package/dist/assets/tts-supertonic.js +156 -0
- package/dist/assets/tts-supertonic.js.map +1 -0
- package/dist/assets/tts.d.ts +18 -6
- package/dist/assets/tts.d.ts.map +1 -1
- package/dist/assets/tts.js +219 -97
- package/dist/assets/tts.js.map +1 -1
- package/dist/cli.js +1685 -93
- package/dist/cli.js.map +1 -1
- package/dist/composition/format.d.ts +1 -1
- package/dist/composition/format.d.ts.map +1 -1
- package/dist/composition/format.js +1 -1
- package/dist/composition/format.js.map +1 -1
- package/dist/context.d.ts +82 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +277 -0
- package/dist/context.js.map +1 -0
- package/dist/contracts.d.ts +25 -0
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/doctor.d.ts +14 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +166 -7
- package/dist/doctor.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/fonts/add.d.ts +41 -0
- package/dist/fonts/add.d.ts.map +1 -0
- package/dist/fonts/add.js +259 -0
- package/dist/fonts/add.js.map +1 -0
- package/dist/fonts/binary.d.ts +4 -0
- package/dist/fonts/binary.d.ts.map +1 -0
- package/dist/fonts/binary.js +21 -0
- package/dist/fonts/binary.js.map +1 -0
- package/dist/fonts/css.d.ts +4 -0
- package/dist/fonts/css.d.ts.map +1 -0
- package/dist/fonts/css.js +50 -0
- package/dist/fonts/css.js.map +1 -0
- package/dist/fonts/fontsource.d.ts +107 -0
- package/dist/fonts/fontsource.d.ts.map +1 -0
- package/dist/fonts/fontsource.js +565 -0
- package/dist/fonts/fontsource.js.map +1 -0
- package/dist/fonts/index.d.ts +11 -0
- package/dist/fonts/index.d.ts.map +1 -0
- package/dist/fonts/index.js +11 -0
- package/dist/fonts/index.js.map +1 -0
- package/dist/fonts/install.d.ts +24 -0
- package/dist/fonts/install.d.ts.map +1 -0
- package/dist/fonts/install.js +145 -0
- package/dist/fonts/install.js.map +1 -0
- package/dist/fonts/manifest.d.ts +21 -0
- package/dist/fonts/manifest.d.ts.map +1 -0
- package/dist/fonts/manifest.js +96 -0
- package/dist/fonts/manifest.js.map +1 -0
- package/dist/fonts/options.d.ts +9 -0
- package/dist/fonts/options.d.ts.map +1 -0
- package/dist/fonts/options.js +66 -0
- package/dist/fonts/options.js.map +1 -0
- package/dist/fonts/schema.d.ts +4 -0
- package/dist/fonts/schema.d.ts.map +1 -0
- package/dist/fonts/schema.js +316 -0
- package/dist/fonts/schema.js.map +1 -0
- package/dist/fonts/summary.d.ts +16 -0
- package/dist/fonts/summary.d.ts.map +1 -0
- package/dist/fonts/summary.js +22 -0
- package/dist/fonts/summary.js.map +1 -0
- package/dist/fonts/types.d.ts +56 -0
- package/dist/fonts/types.d.ts.map +1 -0
- package/dist/fonts/types.js +8 -0
- package/dist/fonts/types.js.map +1 -0
- package/dist/fonts/verify.d.ts +33 -0
- package/dist/fonts/verify.d.ts.map +1 -0
- package/dist/fonts/verify.js +200 -0
- package/dist/fonts/verify.js.map +1 -0
- package/dist/html/validate.d.ts.map +1 -1
- package/dist/html/validate.js +59 -0
- package/dist/html/validate.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +61 -0
- package/dist/inspect.d.ts.map +1 -0
- package/dist/inspect.js +325 -0
- package/dist/inspect.js.map +1 -0
- package/dist/lint.d.ts +63 -0
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +265 -0
- package/dist/lint.js.map +1 -0
- package/dist/policy.d.ts +69 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +361 -0
- package/dist/policy.js.map +1 -0
- package/dist/preview/timeline-data.d.ts +17 -69
- package/dist/preview/timeline-data.d.ts.map +1 -1
- package/dist/preview/timeline-host.d.ts.map +1 -1
- package/dist/preview/timeline-host.js +70 -45
- package/dist/preview/timeline-host.js.map +1 -1
- package/dist/preview/timeline-main.d.ts.map +1 -1
- package/dist/preview/timeline-main.js +47 -4
- package/dist/preview/timeline-main.js.map +1 -1
- package/dist/project.d.ts +10 -3
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +20 -17
- package/dist/project.js.map +1 -1
- package/dist/renderer/ffmpeg.d.ts +42 -2
- package/dist/renderer/ffmpeg.d.ts.map +1 -1
- package/dist/renderer/ffmpeg.js +254 -22
- package/dist/renderer/ffmpeg.js.map +1 -1
- package/dist/renderer/index.js +1 -1
- package/dist/renderer/index.js.map +1 -1
- package/dist/renderer/keyframe-expressions.d.ts +39 -0
- package/dist/renderer/keyframe-expressions.d.ts.map +1 -0
- package/dist/renderer/keyframe-expressions.js +180 -0
- package/dist/renderer/keyframe-expressions.js.map +1 -0
- package/dist/renderer/timeline.d.ts +2 -0
- package/dist/renderer/timeline.d.ts.map +1 -1
- package/dist/renderer/timeline.js +89 -116
- package/dist/renderer/timeline.js.map +1 -1
- package/dist/runtime/host.d.ts.map +1 -1
- package/dist/runtime/host.js +4 -0
- package/dist/runtime/host.js.map +1 -1
- package/dist/scaffold.d.ts +3 -0
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +48 -320
- package/dist/scaffold.js.map +1 -1
- package/dist/server/composition-html.d.ts +2 -0
- package/dist/server/composition-html.d.ts.map +1 -1
- package/dist/server/composition-html.js +7 -0
- package/dist/server/composition-html.js.map +1 -1
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +31 -1
- package/dist/server/server.js.map +1 -1
- package/dist/server/timeline-preview-data.d.ts.map +1 -1
- package/dist/server/timeline-preview-data.js +12 -34
- package/dist/server/timeline-preview-data.js.map +1 -1
- package/dist/server/timeline-preview-html.d.ts.map +1 -1
- package/dist/server/timeline-preview-html.js +18 -2
- package/dist/server/timeline-preview-html.js.map +1 -1
- package/dist/templates.d.ts +16 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +186 -0
- package/dist/templates.js.map +1 -0
- package/dist/timeline/easing.d.ts +36 -0
- package/dist/timeline/easing.d.ts.map +1 -0
- package/dist/timeline/easing.js +225 -0
- package/dist/timeline/easing.js.map +1 -0
- package/dist/timeline/keyframes.d.ts +23 -0
- package/dist/timeline/keyframes.d.ts.map +1 -0
- package/dist/timeline/keyframes.js +95 -0
- package/dist/timeline/keyframes.js.map +1 -0
- package/dist/timeline/plan.d.ts +6 -12
- package/dist/timeline/plan.d.ts.map +1 -1
- package/dist/timeline/plan.js +17 -30
- package/dist/timeline/plan.js.map +1 -1
- package/dist/timeline/resolve.d.ts +12 -0
- package/dist/timeline/resolve.d.ts.map +1 -1
- package/dist/timeline/resolve.js +105 -9
- package/dist/timeline/resolve.js.map +1 -1
- package/dist/timeline/scene.d.ts +126 -0
- package/dist/timeline/scene.d.ts.map +1 -0
- package/dist/timeline/scene.js +109 -0
- package/dist/timeline/scene.js.map +1 -0
- package/dist/timeline/schema.d.ts +31 -0
- package/dist/timeline/schema.d.ts.map +1 -1
- package/dist/timeline/schema.js +240 -9
- package/dist/timeline/schema.js.map +1 -1
- package/dist/timeline/transitions.d.ts +21 -0
- package/dist/timeline/transitions.d.ts.map +1 -0
- package/dist/timeline/transitions.js +23 -0
- package/dist/timeline/transitions.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/adr/0007-make-html-documents-the-composition-unit.md +1 -1
- package/docs/adr/0010-make-timelines-the-render-unit.md +3 -2
- package/docs/adr/0014-compose-timeline-clips-with-css-blend-modes.md +2 -1
- package/docs/adr/0015-inherit-composition-format-from-the-project.md +2 -2
- package/docs/adr/0016-author-compositions-as-html-fragments.md +1 -1
- package/docs/adr/0018-animate-timeline-clips-with-keyframes.md +35 -0
- package/docs/adr/0019-make-same-track-overlap-the-transition-window.md +36 -0
- package/docs/adr/0020-crossfade-audio-clips-on-audio-tracks.md +27 -0
- package/docs/adr/0021-project-timeline-scenes-once.md +32 -0
- package/docs/adr/0022-gate-heavy-operations-with-a-workspace-resource-policy.md +35 -0
- package/docs/adr/0023-pin-fonts-as-project-assets.md +98 -0
- package/docs/migration-0.4.md +2 -2
- package/docs/preview-testing.md +19 -6
- package/docs/{v0.1-design.md → v0.x-design.md} +55 -30
- package/examples/blend/README.md +3 -3
- package/examples/demo/README.md +2 -2
- package/examples/intro/README.md +71 -0
- package/examples/intro/assets/fonts/figtree/LICENSE.txt +93 -0
- package/examples/intro/assets/fonts/figtree/figtree-latin-wght-normal.woff2 +0 -0
- package/examples/intro/assets/fonts/instrument-serif/LICENSE.txt +93 -0
- package/examples/intro/assets/fonts/instrument-serif/instrument-serif-latin-400-italic.woff2 +0 -0
- package/examples/intro/assets/fonts/space-mono/LICENSE.txt +93 -0
- package/examples/intro/assets/fonts/space-mono/space-mono-latin-400-normal.woff2 +0 -0
- package/examples/intro/assets/fonts/space-mono/space-mono-latin-700-normal.woff2 +0 -0
- package/examples/intro/assets/grain.png +0 -0
- package/examples/intro/assets/score.ogg +0 -0
- package/examples/intro/compositions/brand.html +412 -0
- package/examples/intro/compositions/chrome.controller.js +63 -0
- package/examples/intro/compositions/chrome.html +256 -0
- package/examples/intro/compositions/lattice.controller.js +148 -0
- package/examples/intro/compositions/lattice.html +308 -0
- package/examples/intro/compositions/opening.html +504 -0
- package/examples/intro/compositions/studio.html +930 -0
- package/examples/intro/compositions/theme.css +218 -0
- package/examples/intro/fy.config.js +13 -0
- package/examples/intro/fy.fonts.json +100 -0
- package/examples/intro/scripts/make-grain.mjs +79 -0
- package/examples/intro/scripts/make-score.mjs +702 -0
- package/examples/intro/timelines/intro.timeline.json +60 -0
- package/examples/keyframes/README.md +76 -0
- package/examples/keyframes/compositions/backdrop.html +60 -0
- package/examples/keyframes/compositions/card.html +99 -0
- package/examples/keyframes/fy.config.js +10 -0
- package/examples/keyframes/timelines/keyframes.timeline.json +60 -0
- package/examples/nested/README.md +112 -0
- package/examples/nested/assets/pulse.wav +0 -0
- package/examples/nested/compositions/backdrop.html +84 -0
- package/examples/nested/compositions/card.html +275 -0
- package/examples/nested/compositions/overlay.html +307 -0
- package/examples/nested/fy.config.js +13 -0
- package/examples/nested/scripts/make-pulse.sh +20 -0
- package/examples/nested/timelines/chapter-a.timeline.json +39 -0
- package/examples/nested/timelines/chapter-b.timeline.json +39 -0
- package/examples/nested/timelines/nested-reel.timeline.json +52 -0
- package/examples/static/README.md +2 -2
- package/examples/transitions/README.md +128 -0
- package/examples/transitions/assets/alpha.wav +0 -0
- package/examples/transitions/assets/beta.wav +0 -0
- package/examples/transitions/assets/gamma.wav +0 -0
- package/examples/transitions/compositions/alpha.html +56 -0
- package/examples/transitions/compositions/beta.html +56 -0
- package/examples/transitions/compositions/gamma.html +56 -0
- package/examples/transitions/fy.config.js +12 -0
- package/examples/transitions/timelines/audio-crossfade.timeline.json +44 -0
- package/examples/transitions/timelines/transitions.timeline.json +31 -0
- package/examples/video/README.md +4 -4
- package/examples/webgl/README.md +1 -1
- package/package.json +12 -5
- package/scaffolds/init/AGENTS.md +131 -0
- package/scaffolds/init/README.md +56 -0
- package/scaffolds/init/compositions/hello.html +79 -0
- package/scaffolds/init/fy.config.js +9 -0
- package/scaffolds/init/gitignore.template +1 -0
- package/scaffolds/init/package.json +11 -0
- package/scaffolds/init/props/hello.json +4 -0
- package/scaffolds/init/props/main.json +6 -0
- package/scaffolds/init/timelines/main.timeline.json +20 -0
- package/scaffolds/local-models/LOCAL-MODELS.md +77 -0
- package/scaffolds/local-models/fy.policy.json +5 -0
- package/scaffolds/local-models/opencode/opencode.jsonc +17 -0
- package/scaffolds/local-models/pi/APPEND_SYSTEM.md +21 -0
- package/scaffolds/local-models/pi/sandbox.json +15 -0
- package/scaffolds/local-models/pi/settings.json +15 -0
- package/skills/frameyard/README.md +1 -0
- package/skills/frameyard/SKILL.md +59 -61
- package/skills/frameyard/references/audio-assets.md +32 -3
- package/skills/frameyard/references/common-mistakes.md +53 -2
- package/skills/frameyard/references/deterministic-authoring.md +10 -3
- package/skills/frameyard/references/diagnostics.md +31 -1
- package/skills/frameyard/references/failure-recovery.md +32 -6
- package/skills/frameyard/references/fonts.md +132 -0
- package/skills/frameyard/references/json-results.md +119 -6
- package/skills/frameyard/references/quick-reference.md +222 -0
- package/skills/frameyard/references/timelines.md +97 -7
- /package/examples/blend/{video.config.js → fy.config.js} +0 -0
- /package/examples/demo/{video.config.js → fy.config.js} +0 -0
- /package/examples/static/{video.config.js → fy.config.js} +0 -0
- /package/examples/video/{video.config.js → fy.config.js} +0 -0
- /package/examples/webgl/{video.config.js → fy.config.js} +0 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# My Frameyard project
|
|
2
|
+
|
|
3
|
+
Coding agents should read `AGENTS.md` for the project rules and the lint, check, still, and render workflow.
|
|
4
|
+
|
|
5
|
+
The reusable composition is a partial HTML fragment at `compositions/hello.html`. The edit is `timelines/main.timeline.json`, which places that composition as a clip in the project format. The project format is fixed in `fy.config.js`.
|
|
6
|
+
|
|
7
|
+
Start the preview:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npx frameyard dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The preview lists the timeline next to the compositions. Open the timeline to scrub it and inspect the program monitor.
|
|
14
|
+
|
|
15
|
+
Validate and render the timeline:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npx frameyard doctor
|
|
19
|
+
npx frameyard check main
|
|
20
|
+
npx frameyard render main --props props/main.json
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`props/main.json` maps composition clip IDs to props overrides. The video is written to `out/main.mp4` in the project. Pass `--out <file.mp4>` to choose another path. Timelines with heavy composition work accept `--workers <n>` and `--scratch <dir>`.
|
|
24
|
+
|
|
25
|
+
The composition can still be previewed and rendered on its own:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npx frameyard check hello
|
|
29
|
+
npx frameyard render hello --props props/hello.json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Install a font when the design needs one:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
npx frameyard font search "space grotesk" --subset latin --json
|
|
36
|
+
npx frameyard font add space-grotesk --subset latin
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Or vendor a local font:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
npx frameyard font add --file ./fonts/SpaceGrotesk.woff2 \
|
|
43
|
+
--family "Space Grotesk" --license OFL-1.1 --license-file ./fonts/OFL.txt
|
|
44
|
+
npx frameyard font verify
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The server injects the font sheet into every composition; use the family name in CSS. Commit `fy.fonts.json`, `assets/fonts/`, and license files. See `AGENTS.md` for the policy limits.
|
|
48
|
+
|
|
49
|
+
Or run the pinned scripts from `package.json`:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
npm run dev
|
|
53
|
+
npm run check -- main
|
|
54
|
+
npm run render -- main --props props/main.json
|
|
55
|
+
npm run still -- main --frame 42 --out main-42.png
|
|
56
|
+
```
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<script type="application/json" data-fy="props">
|
|
2
|
+
{ "title": "Hello, Frameyard", "accent": "#b8f36b" }
|
|
3
|
+
</script>
|
|
4
|
+
<style>
|
|
5
|
+
@keyframes fade-up {
|
|
6
|
+
from {
|
|
7
|
+
opacity: 0;
|
|
8
|
+
transform: translateY(28px);
|
|
9
|
+
}
|
|
10
|
+
to {
|
|
11
|
+
opacity: 1;
|
|
12
|
+
transform: translateY(0);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
@keyframes drift {
|
|
16
|
+
from {
|
|
17
|
+
transform: translate(-120px, -80px);
|
|
18
|
+
}
|
|
19
|
+
to {
|
|
20
|
+
transform: translate(120px, 80px);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
#hello {
|
|
24
|
+
position: relative;
|
|
25
|
+
width: 100%;
|
|
26
|
+
height: 100%;
|
|
27
|
+
display: grid;
|
|
28
|
+
place-items: center;
|
|
29
|
+
overflow: hidden;
|
|
30
|
+
background: #0b0d10;
|
|
31
|
+
color: #e8edf3;
|
|
32
|
+
font-family: Inter, system-ui, sans-serif;
|
|
33
|
+
}
|
|
34
|
+
#hello h1 {
|
|
35
|
+
position: relative;
|
|
36
|
+
margin: 0;
|
|
37
|
+
font-size: 96px;
|
|
38
|
+
letter-spacing: -0.04em;
|
|
39
|
+
opacity: 0;
|
|
40
|
+
animation: fade-up 1s cubic-bezier(0.215, 0.61, 0.355, 1) both;
|
|
41
|
+
}
|
|
42
|
+
#hello p {
|
|
43
|
+
position: relative;
|
|
44
|
+
margin: 18px 0 0;
|
|
45
|
+
color: #8a97a6;
|
|
46
|
+
font-size: 26px;
|
|
47
|
+
}
|
|
48
|
+
#glow {
|
|
49
|
+
position: absolute;
|
|
50
|
+
left: 50%;
|
|
51
|
+
top: 50%;
|
|
52
|
+
width: 520px;
|
|
53
|
+
height: 520px;
|
|
54
|
+
margin: -260px 0 0 -260px;
|
|
55
|
+
border-radius: 50%;
|
|
56
|
+
background: var(--fy-prop-accent);
|
|
57
|
+
filter: blur(120px);
|
|
58
|
+
opacity: 0.16;
|
|
59
|
+
animation: drift 12s ease-in-out infinite alternate;
|
|
60
|
+
}
|
|
61
|
+
#sweep {
|
|
62
|
+
position: absolute;
|
|
63
|
+
left: 0;
|
|
64
|
+
bottom: 0;
|
|
65
|
+
width: calc(var(--fy-progress) * 100%);
|
|
66
|
+
height: 4px;
|
|
67
|
+
background: var(--fy-prop-accent);
|
|
68
|
+
}
|
|
69
|
+
</style>
|
|
70
|
+
<fy-composition width="1280" height="720" fps="30" duration-in-frames="150">
|
|
71
|
+
<div id="hello">
|
|
72
|
+
<div id="glow"></div>
|
|
73
|
+
<div style="position: relative; text-align: center">
|
|
74
|
+
<h1 id="title" data-fy-text="title" data-fy-anim-start="0" data-fy-anim-duration="24"></h1>
|
|
75
|
+
<p>Deterministic video, authored on the web.</p>
|
|
76
|
+
</div>
|
|
77
|
+
<div id="sweep"></div>
|
|
78
|
+
</div>
|
|
79
|
+
</fy-composition>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
out/
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "npx --yes frameyard@{{VERSION}} dev",
|
|
7
|
+
"check": "npx --yes frameyard@{{VERSION}} check",
|
|
8
|
+
"render": "npx --yes frameyard@{{VERSION}} render",
|
|
9
|
+
"still": "npx --yes frameyard@{{VERSION}} still"
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Optional local-model scaffold
|
|
2
|
+
|
|
3
|
+
Install these files into a workspace when a local model and Frameyard share the
|
|
4
|
+
same machine. They are not active in this repository by default.
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
npx frameyard add local-models
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
For a new project, install the normal scaffold and the host setup together:
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
npx frameyard init my-project --local-models
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Manual copy is still possible:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
mkdir -p .opencode .pi
|
|
20
|
+
cp -R scaffolds/local-models/opencode/. .opencode/
|
|
21
|
+
cp -R scaffolds/local-models/pi/. .pi/
|
|
22
|
+
cp scaffolds/local-models/fy.policy.json .
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The CLI refuses to overwrite an existing file. If the target workspace already
|
|
26
|
+
has an `.opencode/opencode.jsonc` or `.pi/` configuration, merge the scaffold
|
|
27
|
+
instead of copying over it.
|
|
28
|
+
|
|
29
|
+
## What each file does
|
|
30
|
+
|
|
31
|
+
- `fy.policy.json`: the `authoring` tier and `shared-cpu` profile. It
|
|
32
|
+
blocks `tts`, `transcribe`, and `render`; allows `lint`, `context`, `doctor`,
|
|
33
|
+
`add`, `inspect`, `compare`, `font search`, `font list`, `font verify`,
|
|
34
|
+
`font add` without `--force`, `check`, and at most four still frames; and
|
|
35
|
+
denies `--force`/`--overwrite`, `font remove`, and an unlicensed `font add
|
|
36
|
+
--url`. Adjust the tier or profile for the machine. Remove the file to return
|
|
37
|
+
to the default `full` tier.
|
|
38
|
+
- `.opencode/opencode.jsonc`: project-local OpenCode permissions for a local
|
|
39
|
+
model session. It denies the common heavy shell forms and protects
|
|
40
|
+
`fy.policy.json`, `.opencode/`, `.pi/`, and `skills/frameyard/` from
|
|
41
|
+
edits. It also adds `./skills` as a skill search path, which assumes the
|
|
42
|
+
official skill lives in the workspace; remove that line if it does not.
|
|
43
|
+
- `.pi/settings.json`: points Pi at `http://127.0.0.1:9931` and defaults to
|
|
44
|
+
`LFM3-1.7B-Q8_0`, with only `read`, `bash`, `edit`, and `write` enabled.
|
|
45
|
+
- `.pi/APPEND_SYSTEM.md`: the local-model workflow: `context` → `lint` →
|
|
46
|
+
`still` → `check` → handoff with `--dry-run`.
|
|
47
|
+
- `.pi/sandbox.json`: committed but `enabled: false`. Enable it only after
|
|
48
|
+
testing Chromium, FFmpeg, and the local router with the filesystem/network
|
|
49
|
+
rules you need.
|
|
50
|
+
|
|
51
|
+
## Human overrides
|
|
52
|
+
|
|
53
|
+
The policy is a guardrail, not a security boundary. A human who intends to run
|
|
54
|
+
a heavy operation can override it:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
FRAMEYARD_POLICY=full npx frameyard render main --props props/main.json
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The generated example READMEs in this repository use that prefix because they
|
|
61
|
+
may be run with the scaffold installed.
|
|
62
|
+
|
|
63
|
+
## Pi project trust
|
|
64
|
+
|
|
65
|
+
Pi loads `.pi/` only for trusted projects. Either start Pi with:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
pi --approve
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
or add the project to `~/.pi/agent/trust.json` once. The trust entry is the only
|
|
72
|
+
global change; the rest stays in the workspace.
|
|
73
|
+
|
|
74
|
+
## Opting out
|
|
75
|
+
|
|
76
|
+
Remove `fy.policy.json` and the `.opencode/`/`.pi/` files you copied.
|
|
77
|
+
The CLI then defaults to `full`, and the host configuration no longer applies.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://opencode.ai/config.json",
|
|
3
|
+
"skills": ["./skills"],
|
|
4
|
+
"permissions": [
|
|
5
|
+
{ "action": "edit", "resource": "fy.policy.json", "effect": "deny" },
|
|
6
|
+
{ "action": "edit", "resource": ".opencode/**", "effect": "deny" },
|
|
7
|
+
{ "action": "edit", "resource": ".pi/**", "effect": "deny" },
|
|
8
|
+
{ "action": "edit", "resource": "skills/frameyard/**", "effect": "deny" },
|
|
9
|
+
{ "action": "shell", "resource": "*frameyard render*", "effect": "deny" },
|
|
10
|
+
{ "action": "shell", "resource": "*frameyard tts*", "effect": "deny" },
|
|
11
|
+
{ "action": "shell", "resource": "*frameyard transcribe*", "effect": "deny" },
|
|
12
|
+
{ "action": "shell", "resource": "*dist/cli.js render*", "effect": "deny" },
|
|
13
|
+
{ "action": "shell", "resource": "*dist/cli.js tts*", "effect": "deny" },
|
|
14
|
+
{ "action": "shell", "resource": "*dist/cli.js transcribe*", "effect": "deny" },
|
|
15
|
+
{ "action": "shell", "resource": "*--dry-run*", "effect": "allow" },
|
|
16
|
+
],
|
|
17
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Frameyard resource policy
|
|
2
|
+
|
|
3
|
+
This workspace uses `fy.policy.json` at the repository root. Do not edit that
|
|
4
|
+
file, `.pi/`, `.opencode/`, or `skills/frameyard/`.
|
|
5
|
+
|
|
6
|
+
## Working loop
|
|
7
|
+
|
|
8
|
+
1. Run `frameyard lint <id> --json` while editing.
|
|
9
|
+
2. Inspect at most four representative stills with `frameyard still <id> --frame <spec> --json`.
|
|
10
|
+
3. Run `frameyard check <id> --json` once at the end when the active policy allows it.
|
|
11
|
+
4. Do not run `frameyard tts`, `frameyard transcribe`, or `frameyard render` unless the
|
|
12
|
+
user explicitly asks. Use `--dry-run` and report `deferred: true` with the exact
|
|
13
|
+
handoff command instead.
|
|
14
|
+
5. `frameyard font search`, `font list`, and `font verify` are allowed; `font add`
|
|
15
|
+
is allowed without `--force`. `font remove`, `font add --force`, and an
|
|
16
|
+
unlicensed `font add --url` require the `full` policy.
|
|
17
|
+
6. Read `AGENTS.md` and `skills/frameyard/SKILL.md` before changing public behavior.
|
|
18
|
+
|
|
19
|
+
The local llama.cpp router is at `http://127.0.0.1:9931`. Use a small text model for
|
|
20
|
+
the lint loop and a vision-capable model only for representative stills. Do not
|
|
21
|
+
switch to a larger local model just to re-read the same files.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"enabled": false,
|
|
3
|
+
"allowBrowserProcess": false,
|
|
4
|
+
"network": {
|
|
5
|
+
"allowLocalBinding": true,
|
|
6
|
+
"allowAllUnixSockets": true,
|
|
7
|
+
"allowedDomains": [],
|
|
8
|
+
"deniedDomains": []
|
|
9
|
+
},
|
|
10
|
+
"filesystem": {
|
|
11
|
+
"allowRead": [".", "~/.config", "~/.local"],
|
|
12
|
+
"allowWrite": [".", "/tmp"],
|
|
13
|
+
"denyWrite": ["fy.policy.json", ".pi", ".opencode", "skills/frameyard"]
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://pi.dev/schemas/settings.schema.json",
|
|
3
|
+
"llamaSettings": {
|
|
4
|
+
"servers": [
|
|
5
|
+
{
|
|
6
|
+
"url": "http://127.0.0.1:9931",
|
|
7
|
+
"id": "local",
|
|
8
|
+
"name": "Local llama.cpp"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"defaultTools": ["read", "bash", "edit", "write"],
|
|
13
|
+
"defaultProvider": "local",
|
|
14
|
+
"defaultModel": "LFM3-1.7B-Q8_0"
|
|
15
|
+
}
|
|
@@ -25,6 +25,7 @@ When you work inside the Frameyard repository itself, `npx frameyard` resolves t
|
|
|
25
25
|
## Contents
|
|
26
26
|
|
|
27
27
|
- `SKILL.md`: trigger description and operating workflow
|
|
28
|
+
- `references/quick-reference.md`: compact skeletons, command table, policy table, and common fixes
|
|
28
29
|
- `references/deterministic-authoring.md`
|
|
29
30
|
- `references/bindings.md`
|
|
30
31
|
- `references/controllers.md`
|
|
@@ -1,92 +1,90 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: frameyard
|
|
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, 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.
|
|
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.9.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Frameyard
|
|
8
8
|
|
|
9
|
-
Use
|
|
9
|
+
Use the public project format and CLI. Do not add an agent-only runtime, a hosted service, or direct calls to `qwen-tts`, `sherpa-onnx-offline-tts`, or `whisper-cli`.
|
|
10
10
|
|
|
11
|
-
## First
|
|
11
|
+
## First moves
|
|
12
12
|
|
|
13
|
-
1. Find
|
|
14
|
-
2.
|
|
15
|
-
3.
|
|
16
|
-
4. If
|
|
13
|
+
1. Find `fy.config.js` from the working directory upward, or run `npx frameyard init <directory>`.
|
|
14
|
+
2. Run `npx frameyard context --json`; read `format`, `compositions`, `timelines`, `fonts`, the target, its props, and its controller before editing.
|
|
15
|
+
3. Confirm that speech or transcription is requested or explicitly approved before producing assets.
|
|
16
|
+
4. If context is small, read [quick reference](references/quick-reference.md) first. Router: static/card → quick reference; timelines → [timelines](references/timelines.md); fonts → [fonts](references/fonts.md); captions → [subtitles and karaoke](references/subtitles-karaoke.md); failures → [diagnostics](references/diagnostics.md) and [failure recovery](references/failure-recovery.md); Canvas/WebGL → [controllers](references/controllers.md).
|
|
17
17
|
|
|
18
18
|
## Workflow
|
|
19
19
|
|
|
20
|
-
1. **Author
|
|
21
|
-
2. **Assemble
|
|
22
|
-
3. **Provide props** as JSON. Composition props merge over defaults; timeline
|
|
23
|
-
4. **
|
|
24
|
-
5. **
|
|
25
|
-
6. **Inspect**
|
|
26
|
-
7. **Render** with `npx frameyard render <id> [--out <file>] [--props <file>] --json`.
|
|
27
|
-
8. **Report** the project
|
|
20
|
+
1. **Author** one `<fy-composition>` fragment. Props, the controller, import maps, and styles are top-level siblings; never add a document shell. Omit `duration-in-frames` and `fps` only for a static composition, which renders to PNG and cannot use animation/media/transcripts. Use a controller only for Canvas, WebGL, karaoke, or per-frame math. Read [deterministic authoring](references/deterministic-authoring.md).
|
|
21
|
+
2. **Assemble** a version-1 timeline with explicit tracks and clips. Sources are composition IDs, nested timeline IDs, or local media. `start`, `sourceIn`, and `duration` are integer frames; no remote URLs. Read [timelines](references/timelines.md).
|
|
22
|
+
3. **Provide props** as JSON. Composition props merge over defaults; timeline overrides are keyed by composition clip ID. Use `validateProps()` for domain rules.
|
|
23
|
+
4. **Lint** with `npx frameyard lint <id> --json`. It validates the document/timeline, resolves references, projects every timeline scene/keyframe channel, scans controller determinism, and probes media metadata without Chromium. It is the edit loop, not the full gate.
|
|
24
|
+
5. **Check** with `npx frameyard check <id> --json`. Every animated frame is evaluated, or a static composition once. Read `diagnostics` and `kind`; treat warnings as actionable.
|
|
25
|
+
6. **Inspect** with `npx frameyard still <id> --frame <spec> --out <path> --json`. A spec is a frame, an inclusive range, or a comma-separated list. The policy allows at most 32 unique frames in `full` (4 in `authoring`, 1 in `light`). One frame uses a `.png` file; multiple frames use a directory. Use `npx frameyard inspect`/`compare` for text facts, and view the PNGs when the host supports it; if not, say so.
|
|
26
|
+
7. **Render** with `npx frameyard render <id> [--out <file>] [--props <file>] --json`. Composition renders accept `--concurrency`; timeline renders accept `--workers` and `--scratch`; `--container`, `--codec`, and `--encoder` select delivery. A static composition rejects those four flags. If the policy blocks render, use `--dry-run` and hand off the command; do not claim a render.
|
|
27
|
+
8. **Report** the project, entries, controller, props, generated assets, validation, diagnostics, still paths and inspection status, video path, and failures. Never claim success when `check` fails, a still is missing, a render exits nonzero, or inspection was skipped.
|
|
28
|
+
|
|
29
|
+
## Authoring contract
|
|
30
|
+
|
|
31
|
+
- A composition is a partial fragment with one top-level `<fy-composition>` and a top-level `data-fy="props"` block. Do not use `data-fy-host` or `data-fy="format"`. `width`, `height`, and `fps` inherit the project `format`; declare both dimensions together.
|
|
32
|
+
- A static composition has neither `duration-in-frames` nor `fps`; it runs `mount()`/`validateProps()`, not `update()`, and has no frame-state variables. Declaring `fps` without `duration-in-frames` is an error. A static timeline clip needs an explicit `duration` and `sourceIn: 0`.
|
|
33
|
+
- Bindings: `data-fy-text`, `data-fy-attr-*`, `data-fy-class-*`, `data-fy-if`, and `<template data-fy-repeat>`. Primitive top-level props are also `--fy-prop-<name>` CSS variables. Bindings apply once, before `mount`.
|
|
34
|
+
- CSS/WAAPI animations are seeked from the frame clock. `data-fy-anim-start`, `data-fy-anim-duration`, and `data-fy-anim-easing` schedule one animation in frames. Frame state: `--fy-frame`, `--fy-time`, `--fy-progress`, `--fy-fps`, `--fy-duration`, `--fy-duration-frames`.
|
|
35
|
+
- Exactly one optional controller, inline or external, is the only executable code. It may export `mount`, `update`, `dispose`, and `validateProps`; at least one is required. Other scripts and `on*` handlers are rejected.
|
|
36
|
+
- Media and transcript `src` values resolve from the project root; controller `src` and ordinary HTML URLs resolve from the composition URL. Embedded media uses `data-fy-start` (frames), `data-fy-trim` (seconds), optional `data-fy-duration` (seconds), and `data-fy-volume` (0-1). Transcripts use `<fy-transcript src words>`.
|
|
37
|
+
- An optional top-level import map may add bare specifiers for controllers; `frameyard` and `frameyard/` are reserved.
|
|
38
|
+
|
|
39
|
+
## Determinism
|
|
40
|
+
|
|
41
|
+
- A composition frame depends only on its integer `frame`, immutable `props`, and assets loaded before frame production. A timeline frame derives from its active clips.
|
|
42
|
+
- Use `random("stable:key")` from `frameyard/runtime`; never `Math.random()`. Never use `Date.now()`, `performance.now()`, timers, independent `requestAnimationFrame` loops, or CSS transitions as animation inputs.
|
|
43
|
+
- Load remote data, fonts, and images before frame production. Network is blocked during capture. Prefer project fonts installed with `npx frameyard font add`; remote font URLs produce `FONT_REMOTE` and are not reproducible. Keep `update({ frame, props })` synchronous and seek-safe; do not carry state between frames.
|
|
44
|
+
- Let the runtime seek embedded video; do not play, pause, or set `currentTime` in `update()`. Redraw WebGL from the current frame; production pins software WebGL.
|
|
45
|
+
- Do not run model inference inside `mount()`, `update()`, or frame production.
|
|
28
46
|
|
|
29
|
-
|
|
47
|
+
## Resource policy
|
|
30
48
|
|
|
31
|
-
|
|
49
|
+
`fy.policy.json` is read from the working directory upward, independent of `fy.config.js`; `FRAMEYARD_POLICY` overrides it.
|
|
32
50
|
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
- `
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
- For a timeline, `--props` is a JSON object keyed by top-level composition clip ID. For a composition, it is the props object.
|
|
41
|
-
- Use `npx frameyard doctor --json` before reporting an environment problem. It inspects without repairing or downloading.
|
|
42
|
-
- Read [JSON results](references/json-results.md) for result and error shapes, and [failure recovery](references/failure-recovery.md) for actionable error codes.
|
|
43
|
-
|
|
44
|
-
## Authoring rules
|
|
45
|
-
|
|
46
|
-
- A composition is a partial HTML fragment with one top-level `<fy-composition>` root and a top-level `data-fy="props"` default-props block. Props, the controller, and import maps are top-level siblings of the root; top-level `<style>` and `<link rel="stylesheet">` elements are hoisted into the generated head. Do not use the reserved `data-fy-host` attribute or `data-fy="format"` block. `width`, `height`, and `fps` are optional and inherit from the project `format`; declare them to override it.
|
|
47
|
-
- A composition with neither `duration-in-frames` nor `fps` is static. It is captured once and renders to PNG. It may use `<img>`, CSS, SVG, and canvas, but not `data-fy-anim-*`, `<video>`, `<audio>`, or `<fy-transcript>`. Its controller runs `mount()` and `validateProps()`; `update()` is not called and frame-state variables are not set. CSS animations are paused at time 0. Declaring `fps` without `duration-in-frames` is an error. A static composition clip in a timeline needs an explicit `duration` and `sourceIn: 0`.
|
|
48
|
-
- A timeline is a versioned JSON document with explicit tracks and clips. Sources are composition IDs, nested timeline IDs, or local video/image/audio paths. Timeline frames, sourceIn, and duration are integer frames. No remote URLs.
|
|
49
|
-
- Bindings are explicit: `data-fy-text`, `data-fy-attr-*`, `data-fy-class-*`, `data-fy-if`, and `data-fy-repeat` on `<template>`. Primitive top-level props are also `--fy-prop-<name>` CSS variables.
|
|
50
|
-
- CSS `@keyframes` and the Web Animations API are seeked from the frame clock. `data-fy-anim-start`, `data-fy-anim-duration`, and `data-fy-anim-easing` schedule one animation per element in frames.
|
|
51
|
-
- Frame-state variables on `:root`: `--fy-frame`, `--fy-time`, `--fy-progress`, `--fy-fps`, `--fy-duration`, and `--fy-duration-frames`.
|
|
52
|
-
- A composition has exactly one optional controller, inline or external. It may export `mount`, `update`, `dispose`, and `validateProps`; at least one is required. Use inline for small controllers; extract to an external module for Canvas 2D, WebGL, karaoke, reuse, tests, or a large controller.
|
|
53
|
-
- The controller is the only executable code. Other executable scripts and `on*` handlers are rejected.
|
|
54
|
-
- Media and transcript `src` values resolve from the project root. The controller `src` and ordinary HTML asset URLs resolve relative to the composition URL.
|
|
55
|
-
- Embedded video/audio use `data-fy-start` (frames), `data-fy-trim` (seconds), optional `data-fy-duration` (seconds), and `data-fy-volume` (0-1). Transcripts use `<fy-transcript src words>`.
|
|
56
|
-
- An optional top-level `<script type="importmap">` may add bare specifiers for controllers. Frameyard hoists it before the host module; `frameyard` and `frameyard/` specifiers are reserved.
|
|
57
|
-
|
|
58
|
-
## Determinism guardrails
|
|
59
|
-
|
|
60
|
-
- A composition frame may depend only on its integer `frame`, immutable `props`, and assets loaded before frame production. A timeline frame derives from its active clips and the same composition rules.
|
|
61
|
-
- Use `random("stable:key")` from `frameyard/runtime`; never use `Math.random()`.
|
|
62
|
-
- Never use `Date.now()`, `performance.now()`, timers, independent `requestAnimationFrame` loops, or CSS transitions as animation inputs.
|
|
63
|
-
- Finish remote data, fonts, and image loading during the loading phase. Network requests are blocked during frame capture.
|
|
64
|
-
- Keep `update({ frame, props })` synchronous and seek-safe. Do not carry state between frames.
|
|
65
|
-
- Let the runtime seek embedded `<video>` elements. Do not play, pause, or set `currentTime` in `update()`.
|
|
66
|
-
- Redraw WebGL canvases from the current frame. Production pins software WebGL; do not depend on GPU-specific results or the previous frame's drawing buffer.
|
|
67
|
-
- Do not run model inference inside `mount()`, `update()`, or frame production.
|
|
51
|
+
- `light`: one still frame; blocks `check`, `tts`, `transcribe`, and `render`.
|
|
52
|
+
- `authoring`: four still frames and `check` at low priority; blocks `tts`, `transcribe`, and `render`.
|
|
53
|
+
- `full`: everything up to the 32-frame still cap.
|
|
54
|
+
- `lint`, `context`, `doctor`, `add`, `inspect`, `compare`, and `--dry-run` are available in every tier. `font search`, `font list`, and `font verify` are available in every tier; `font add` requires `authoring` or `full`; `font remove`, `font add --force`, and `font add --url` without `--license`/`--license-file` require `full`.
|
|
55
|
+
- When blocked, run `--dry-run`, report `deferred: true`, and give the user `commandLine`, `prerequisites`, and `blockers`. Never claim a render or asset exists.
|
|
56
|
+
- `--profile shared-cpu` caps timeline workers at 2 and composition concurrency at 1 and lowers priority; `--low-priority` lowers priority without caps. Values above a cap fail with `RESOURCE_PROFILE_CONFLICT`; do not clamp silently.
|
|
57
|
+
- `light`/`authoring` deny `--force` and `--overwrite`; ask before replacing an output. Do not edit the policy file, host configuration, or skill source. The policy is a guardrail, not a security boundary.
|
|
68
58
|
|
|
69
|
-
##
|
|
59
|
+
## Command rules
|
|
60
|
+
|
|
61
|
+
- Use `--json` for non-interactive commands; parse stdout, keep stderr for progress/diagnostics. Use `--project <dir>` outside the project root.
|
|
62
|
+
- Outputs default to `out/<id>.<ext>` for video and `out/<id>.png` for static compositions; explicit `--out` is relative to the current directory. Replace outputs only with approval.
|
|
63
|
+
- For a timeline, `--props` is a map keyed by top-level composition clip ID; for a composition, it is the props object. Use `--concurrency` for animated compositions, `--workers`/`--scratch` for timelines. `--container <mp4|mov|mkv|webm>`, `--codec <h264|hevc|vp9>`, and `--encoder <auto|software|nvenc|qsv>` select delivery; the output extension must match the container.
|
|
64
|
+
- Produce speech and transcripts only with `npx frameyard tts` and `npx frameyard transcribe`, never upstream executables; read [audio assets](references/audio-assets.md). Do not overwrite generated assets without approval.
|
|
65
|
+
- Use `npx frameyard add --list --json` and `add composition|timeline <id> --template <name> --json` for templates; merge the returned registration object into `fy.config.js`. `add` never edits the config or overwrites an entry.
|
|
66
|
+
- Use `npx frameyard font search <query> --json` to find a Fontsource family, then `npx frameyard font add <fontsource-id> --json` to pin and vendor it. Use `font add --file` for a local or brand font, or `font add --url` for an explicit HTTPS source. Reference the returned CSS family. `font list`, `font verify`, and `font remove` manage the manifest; never edit `fy.fonts.json` hashes by hand. Read [fonts](references/fonts.md).
|
|
67
|
+
- Use `npx frameyard doctor --json` before reporting an environment problem. Read [JSON results](references/json-results.md) and [failure recovery](references/failure-recovery.md).
|
|
70
68
|
|
|
71
|
-
|
|
69
|
+
## Diagnostics and karaoke
|
|
72
70
|
|
|
73
|
-
|
|
71
|
+
`check`, `still`, and `render` run static validation before Chromium; errors stop, warnings allow frames. Diagnostics carry a stable `code`, message, and optional source location/suggestion. Treat `BINDING_PATH_MISSING`, `ANIMATION_*`, `STATIC_*`, and `DETERMINISM_WARNING` as actionable.
|
|
74
72
|
|
|
75
|
-
Use
|
|
73
|
+
Use transcripts from `npx frameyard transcribe`. Convert source-relative milliseconds to composition frames with the clip start, trim start, and `fps`. Karaoke requires measured `words`; never interpolate segment timings.
|
|
76
74
|
|
|
77
75
|
## CLI invocation
|
|
78
76
|
|
|
79
|
-
Use `npx frameyard`
|
|
77
|
+
Use `npx frameyard` or an installed binary. `scripts/frameyard.mjs` is the fallback; set `FRAMEYARD_CLI` when the command is unavailable. Pin the CLI with `npx frameyard@<version>` when it differs from `frameyard-api-version`.
|
|
80
78
|
|
|
81
79
|
```sh
|
|
82
80
|
npx frameyard check <id> --json
|
|
83
|
-
node scripts/frameyard.mjs check <id> --json
|
|
81
|
+
node scripts/frameyard.mjs check <id> --json
|
|
84
82
|
```
|
|
85
83
|
|
|
86
|
-
When the CLI version differs from `frameyard-api-version`, pin it with `npx frameyard@<version>`.
|
|
87
|
-
|
|
88
84
|
## References
|
|
89
85
|
|
|
86
|
+
- [Quick reference](references/quick-reference.md)
|
|
87
|
+
- [Fonts](references/fonts.md)
|
|
90
88
|
- [Timelines](references/timelines.md)
|
|
91
89
|
- [Deterministic HTML authoring](references/deterministic-authoring.md)
|
|
92
90
|
- [Bindings](references/bindings.md)
|
|
@@ -34,7 +34,9 @@ Declare required transcripts with:
|
|
|
34
34
|
|
|
35
35
|
## Local speech synthesis
|
|
36
36
|
|
|
37
|
-
Use Frameyard
|
|
37
|
+
Use Frameyard instead of calling the upstream executables directly:
|
|
38
|
+
|
|
39
|
+
### qwentts.cpp (default)
|
|
38
40
|
|
|
39
41
|
```sh
|
|
40
42
|
npx frameyard tts \
|
|
@@ -47,6 +49,7 @@ npx frameyard tts \
|
|
|
47
49
|
--json
|
|
48
50
|
```
|
|
49
51
|
|
|
52
|
+
- `--engine qwen` is the default and may be omitted.
|
|
50
53
|
- CustomVoice only: `--speaker` is required.
|
|
51
54
|
- Text comes from `--text-file` or stdin.
|
|
52
55
|
- `--style` maps to the upstream style instruction.
|
|
@@ -58,6 +61,28 @@ npx frameyard tts \
|
|
|
58
61
|
- Executable resolution: `--executable`, then `FRAMEYARD_QWEN_TTS`, then `PATH`.
|
|
59
62
|
- Frameyard does not build qwentts.cpp, download models, or redistribute weights.
|
|
60
63
|
|
|
64
|
+
### Supertonic 3
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
npx frameyard tts \
|
|
68
|
+
--engine supertonic \
|
|
69
|
+
--speaker 0 \
|
|
70
|
+
--model-dir models/sherpa-onnx-supertonic-3-tts-int8-2026-05-11 \
|
|
71
|
+
--language es \
|
|
72
|
+
--text-file script.txt \
|
|
73
|
+
--out assets/voice-es.wav \
|
|
74
|
+
--json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
- The engine covers 31 languages and requires one of their codes (`es`, `en`, `fr`, `de`, ...); `--language` is mandatory.
|
|
78
|
+
- `--speaker` is the numeric `--sid`, not a name.
|
|
79
|
+
- `--model-dir` points at the extracted Supertonic 3 archive with its seven files; do not pass individual files.
|
|
80
|
+
- `--style` and `--device` are qwen-only. Put Supertonic expression tags such as `<laugh>`, `<breath>`, and `<sigh>` in the text.
|
|
81
|
+
- The engine writes its native WAV; Frameyard normalizes it to 24 kHz mono and records `sourceSampleRate` and `sourceChannels` in the manifest.
|
|
82
|
+
- `--force` is required to replace an existing asset. Do not pass it without user approval.
|
|
83
|
+
- Executable resolution: `--executable`, then `FRAMEYARD_SHERPA_ONNX_TTS`, then `PATH`.
|
|
84
|
+
- Frameyard does not build sherpa-onnx, download the model archive, or redistribute weights. The upstream Supertonic repository is archived and its weights use the OpenRAIL-M license.
|
|
85
|
+
|
|
61
86
|
## Local transcription
|
|
62
87
|
|
|
63
88
|
```sh
|
|
@@ -77,9 +102,13 @@ npx frameyard transcribe assets/voice.wav \
|
|
|
77
102
|
- Executable resolution: `--executable`, then `FRAMEYARD_WHISPER_CLI`, then `PATH`.
|
|
78
103
|
- Frameyard does not download Whisper models or execute Whisper's generated karaoke shell script.
|
|
79
104
|
|
|
105
|
+
## Pinned upstream revisions
|
|
106
|
+
|
|
107
|
+
The wrappers target the CLI surfaces of qwentts.cpp commit `5916bf7c79dbb4e66fc059cdc507a79a23a28bb4`, sherpa-onnx commit `af2d8d81dbfa61c4cea4c568da78f3982edca005` (v2.0.1), and whisper.cpp commit `284029c07012d2000941a08d38a31ffb71f4734e`.
|
|
108
|
+
|
|
80
109
|
## Provenance manifest
|
|
81
110
|
|
|
82
|
-
Both commands update `
|
|
111
|
+
Both commands update `fy.assets.json` in the project root unless `--manifest <file>` is supplied. The manifest records:
|
|
83
112
|
|
|
84
113
|
- artifact path, content hash, and size;
|
|
85
114
|
- generator command, Frameyard version, executable, and integration revision;
|
|
@@ -93,5 +122,5 @@ Commit the manifest with the project. It explains how generated inputs were prod
|
|
|
93
122
|
- Do not regenerate or overwrite an existing generated asset without permission.
|
|
94
123
|
- Do not silently switch models, speakers, language, or text.
|
|
95
124
|
- Report the manifest path and the exact asset paths after success.
|
|
96
|
-
- `npx frameyard doctor` verifies manifest integrity, including artifact, source, model, and derived-export hashes, and optional integration executables; it does not download or repair anything. Pass `--talker-model`, `--codec-model`, or `--model` to inspect model readability and identity before generation.
|
|
125
|
+
- `npx frameyard doctor` verifies manifest integrity, including artifact, source, model, and derived-export hashes, and optional integration executables; it does not download or repair anything. Pass `--talker-model`, `--codec-model`, `--model-dir`, or `--model` to inspect model readability and identity before generation.
|
|
97
126
|
- Once assets are frozen, checking and rendering do not need the model or inference executable.
|