visualfries 0.1.10120 → 0.3.2
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/README.md +97 -0
- package/bin/visualfries.js +1570 -0
- package/dist/DIContainer.d.ts +2 -1
- package/dist/DIContainer.js +16 -5
- package/dist/SceneBuilder.svelte.d.ts +70 -1
- package/dist/SceneBuilder.svelte.js +96 -29
- package/dist/agent/audioMixer.d.ts +34 -0
- package/dist/agent/audioMixer.js +308 -0
- package/dist/agent/broll.d.ts +35 -0
- package/dist/agent/broll.js +226 -0
- package/dist/agent/capabilities.d.ts +34 -0
- package/dist/agent/capabilities.js +246 -0
- package/dist/agent/captionScene.d.ts +23 -0
- package/dist/agent/captionScene.js +204 -0
- package/dist/agent/catalog.d.ts +24 -0
- package/dist/agent/catalog.js +67 -0
- package/dist/agent/cueFiles.d.ts +54 -0
- package/dist/agent/cueFiles.js +219 -0
- package/dist/agent/cuePresets.d.ts +7 -0
- package/dist/agent/cuePresets.js +50 -0
- package/dist/agent/deterministicMedia.d.ts +61 -0
- package/dist/agent/deterministicMedia.js +303 -0
- package/dist/agent/index.d.ts +18 -0
- package/dist/agent/index.js +18 -0
- package/dist/agent/inspectScene.d.ts +36 -0
- package/dist/agent/inspectScene.js +139 -0
- package/dist/agent/localRender.d.ts +82 -0
- package/dist/agent/localRender.js +702 -0
- package/dist/agent/overlays.d.ts +40 -0
- package/dist/agent/overlays.js +325 -0
- package/dist/agent/productionPlan.d.ts +131 -0
- package/dist/agent/productionPlan.js +322 -0
- package/dist/agent/renderPlan.d.ts +27 -0
- package/dist/agent/renderPlan.js +68 -0
- package/dist/agent/renderRanges.d.ts +24 -0
- package/dist/agent/renderRanges.js +73 -0
- package/dist/agent/runtimeSupport.d.ts +19 -0
- package/dist/agent/runtimeSupport.js +192 -0
- package/dist/agent/streamingEncoder.d.ts +31 -0
- package/dist/agent/streamingEncoder.js +208 -0
- package/dist/agent/transcripts.d.ts +29 -0
- package/dist/agent/transcripts.js +146 -0
- package/dist/agent/transitions.d.ts +20 -0
- package/dist/agent/transitions.js +169 -0
- package/dist/animations/PixiAnimationTarget.d.ts +29 -0
- package/dist/animations/PixiAnimationTarget.js +63 -0
- package/dist/animations/builders/LineHighlighterAnimationBuilder.js +20 -3
- package/dist/animations/builders/WordHighlighterAnimationBuilder.js +15 -2
- package/dist/browser/browserExport.d.ts +73 -0
- package/dist/browser/browserExport.js +180 -0
- package/dist/browser/glTransitions.d.ts +37 -0
- package/dist/browser/glTransitions.js +261 -0
- package/dist/browser/index.d.ts +3 -0
- package/dist/browser/index.js +3 -0
- package/dist/browser/mediaDecode.d.ts +31 -0
- package/dist/browser/mediaDecode.js +152 -0
- package/dist/builders/PixiComponentBuilder.d.ts +6 -0
- package/dist/builders/PixiComponentBuilder.js +12 -0
- package/dist/builders/_ComponentState.svelte.d.ts +7 -5
- package/dist/builders/_ComponentState.svelte.js +29 -15
- package/dist/builders/html/StyleBuilder.js +9 -8
- package/dist/builders/html/TextComponentHtmlBuilder.js +4 -2
- package/dist/builders/html/processors/AppearanceStyleProcessor.js +1 -1
- package/dist/builders/html/processors/TextAppearanceStyleProcessor.js +7 -0
- package/dist/builders/html/processors/TextEffectsStyleProcessor.js +32 -13
- package/dist/commands/ReplaceSourceOnTimeCommand.js +9 -1
- package/dist/commands/SeekCommand.js +19 -6
- package/dist/components/AnimatedGIF.d.ts +3 -0
- package/dist/components/AnimatedGIF.js +28 -1
- package/dist/components/Component.svelte.d.ts +5 -5
- package/dist/components/Component.svelte.js +29 -13
- package/dist/components/ComponentContext.svelte.js +68 -23
- package/dist/components/hooks/AnimationHook.js +1 -1
- package/dist/components/hooks/CanvasFillHook.d.ts +12 -0
- package/dist/components/hooks/CanvasFillHook.js +75 -0
- package/dist/components/hooks/DeterministicMediaFrameHook.js +3 -0
- package/dist/components/hooks/HtmlTextHook.js +11 -3
- package/dist/components/hooks/HtmlToCanvasHook.js +8 -25
- package/dist/components/hooks/MediaHook.js +172 -47
- package/dist/components/hooks/MediaSeekingHook.js +138 -88
- package/dist/components/hooks/PixiGifHook.js +4 -4
- package/dist/components/hooks/PixiSplitScreenDisplayObjectHook.js +73 -6
- package/dist/components/hooks/PixiVideoTextureHook.js +10 -4
- package/dist/components/hooks/PixiVisualTransformHook.d.ts +16 -0
- package/dist/components/hooks/PixiVisualTransformHook.js +102 -0
- package/dist/components/hooks/SubtitlesHook.js +48 -24
- package/dist/components/hooks/VerifyMediaHook.js +2 -2
- package/dist/directors/ComponentDirector.d.ts +1 -0
- package/dist/directors/ComponentDirector.js +41 -8
- package/dist/fonts/fontDiscovery.js +12 -1
- package/dist/layers/Layer.svelte.d.ts +54 -0
- package/dist/layers/Layer.svelte.js +2 -25
- package/dist/managers/AppManager.svelte.js +8 -5
- package/dist/managers/ComponentsManager.svelte.d.ts +7 -7
- package/dist/managers/ComponentsManager.svelte.js +29 -15
- package/dist/managers/DeterministicMediaManager.js +38 -3
- package/dist/managers/EventManager.js +3 -1
- package/dist/managers/LayersManager.svelte.d.ts +54 -0
- package/dist/managers/RenderManager.d.ts +5 -0
- package/dist/managers/RenderManager.js +67 -21
- package/dist/managers/StateManager.svelte.d.ts +56 -0
- package/dist/managers/StateManager.svelte.js +60 -58
- package/dist/managers/SubtitlesManager.svelte.js +1 -3
- package/dist/managers/TimeManager.svelte.d.ts +4 -0
- package/dist/managers/TimeManager.svelte.js +23 -7
- package/dist/schemas/runtime/deterministic.js +5 -1
- package/dist/schemas/runtime/types.d.ts +36 -15
- package/dist/schemas/scene/components.d.ts +126 -0
- package/dist/schemas/scene/components.js +11 -0
- package/dist/schemas/scene/core.d.ts +109 -10
- package/dist/schemas/scene/core.js +1 -1
- package/dist/utils/mediaWindow.d.ts +13 -0
- package/dist/utils/mediaWindow.js +25 -0
- package/dist/utils/svgGenerator.js +1 -1
- package/dist/utils/timelineWindow.d.ts +2 -0
- package/dist/utils/timelineWindow.js +7 -0
- package/dist/utils/utils.js +2 -4
- package/docs/AGENT_PATTERNS.md +243 -0
- package/docs/AGENT_WORKFLOW.md +364 -0
- package/docs/AUTHORING_BEST_PRACTICES.md +188 -0
- package/docs/AUTHORING_SYSTEM_AUDIT.md +98 -0
- package/docs/BROWSER_EXPORT_SPIKE.md +55 -0
- package/docs/DETERMINISTIC_RENDERER.md +83 -0
- package/docs/NEXT_RELEASE.md +28 -0
- package/docs/PROPOSED_VISUALFRIES_SKILL.md +68 -0
- package/docs/examples/agent-cues.json +49 -0
- package/docs/examples/agent-transcript.json +23 -0
- package/docs/examples/agent-transcript.srt +7 -0
- package/docs/examples/agent-transcript.vtt +7 -0
- package/docs/examples/image-animation.json +87 -0
- package/docs/examples/native-text-metric-badge.json +109 -0
- package/package.json +133 -100
- package/skills/visualfries/SKILL.md +328 -0
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
# VisualFries Agent Workflow
|
|
2
|
+
|
|
3
|
+
This document defines the agent-facing contract for VisualFries.
|
|
4
|
+
|
|
5
|
+
Read [Authoring Best Practices](AUTHORING_BEST_PRACTICES.md) before authoring. It defines the
|
|
6
|
+
native semantic component policy, runtime support matrix, effect/compositing limits, and required
|
|
7
|
+
entry/settled/exit/reseek frame QA. Validation and inspection are structural gates, not rendering
|
|
8
|
+
proof.
|
|
9
|
+
|
|
10
|
+
## Goal
|
|
11
|
+
|
|
12
|
+
Make VisualFries usable by agents without requiring the ContentFries UI:
|
|
13
|
+
|
|
14
|
+
1. create render-ready scene JSON,
|
|
15
|
+
2. add captions from transcripts,
|
|
16
|
+
3. validate and inspect scenes,
|
|
17
|
+
4. render fast QA previews through the CLI browser adapter,
|
|
18
|
+
5. hand final VIDEO/GIF scenes to the local deterministic renderer path.
|
|
19
|
+
|
|
20
|
+
## CLI
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
visualfries validate <scene.json> [--json]
|
|
24
|
+
visualfries inspect <scene.json> [--json] [--screenshots --output <dir>]
|
|
25
|
+
visualfries init <dir> [--video <video> --transcript <file>]
|
|
26
|
+
visualfries caption-scene --video <video> --transcript <file> --output <scene.json>
|
|
27
|
+
visualfries preset-cues --duration <seconds> --output <cues.json>
|
|
28
|
+
visualfries validate-cues <cues.json> [--duration <seconds>] [--json]
|
|
29
|
+
visualfries apply-cues <scene.json> --cues <cues.json> --output <scene.json>
|
|
30
|
+
visualfries qa <scene.json> --output <dir>
|
|
31
|
+
visualfries compose --video <video> --transcript <file> --output <out.mp4>
|
|
32
|
+
visualfries produce <production-plan.json> --output <out.mp4> --scene-output <scene.json> --qa-output <dir>
|
|
33
|
+
visualfries render <scene.json> --output <out.mp4|frames-dir> [--frames-only]
|
|
34
|
+
visualfries catalog [--json]
|
|
35
|
+
visualfries doctor [--json]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Use `produce` for authored edits that need more than captions plus generic cues. A production plan groups the edit into named beats and supports source trims, automatic video freeze-frame holds, native TEXT editorial overlays, exact multi-track audio, transitions, and QA frames. Visible typography compiles to native TEXT by default. `renderAs: "SVG"` is an explicit compatibility fallback for a documented native limitation. The command emits ordinary VisualFries scene JSON, renders at timeline event boundaries, then checks the finished audio lead-in.
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"version": 1,
|
|
43
|
+
"id": "proof-hook",
|
|
44
|
+
"settings": { "width": 1080, "height": 1920, "duration": 6, "fps": 30 },
|
|
45
|
+
"beats": [
|
|
46
|
+
{
|
|
47
|
+
"id": "reaction",
|
|
48
|
+
"start": 0,
|
|
49
|
+
"end": 3,
|
|
50
|
+
"media": [
|
|
51
|
+
{ "id": "reaction", "url": "./reaction.mp4", "start": 0, "end": 3, "freezeAt": 1.8 }
|
|
52
|
+
],
|
|
53
|
+
"overlays": [{ "text": "NOT DEAD.", "start": 1.8, "end": 3, "style": "verdict-slam" }]
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
"audio": [{ "id": "voice", "url": "./voice.wav", "startAt": 0, "volume": 1 }],
|
|
57
|
+
"transitions": [{ "time": 3, "style": "focus-pull" }],
|
|
58
|
+
"qa": { "framesAt": [0.1, 1.9, 3.1], "maxLeadingSilence": 0.1, "requiredText": ["NOT DEAD."] }
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
visualfries produce ./production-plan.json \
|
|
64
|
+
--scene-output ./scene.json \
|
|
65
|
+
--qa-output ./qa \
|
|
66
|
+
--output ./final.mp4
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`render` uses a controlled Vite browser page, Playwright, and `ffmpeg` for static scenes and fast previews. It never requires opening ContentFries UI.
|
|
70
|
+
|
|
71
|
+
Important render contract:
|
|
72
|
+
|
|
73
|
+
- `--render-mode final` is the default.
|
|
74
|
+
- Final scenes with `VIDEO` or `GIF` components require the local deterministic renderer. Native browser media seek is not trusted for final output because it can create stale, duplicated, or shifted frames.
|
|
75
|
+
- Use `--render-mode preview` for quick QA frames or rough local checks.
|
|
76
|
+
- `--allow-browser-media-final` exists only as an escape hatch for experiments. Do not use it for shipped output.
|
|
77
|
+
- In final mode, the CLI predecodes active `VIDEO`/`GIF` ranges to exact frame images and injects a deterministic media provider into the render page.
|
|
78
|
+
|
|
79
|
+
Useful render options:
|
|
80
|
+
|
|
81
|
+
- `--frames-only` renders a PNG frame sequence for QA instead of MP4.
|
|
82
|
+
- `--render-mode preview` permits the browser preview path for VIDEO/GIF scenes.
|
|
83
|
+
- `--engine browser-preview` or `--engine deterministic-local` can force renderer planning when debugging.
|
|
84
|
+
- `--from-frame <n>` and `--to-frame <n>` render a partial range for fast checks.
|
|
85
|
+
- Full contiguous renders use the browser-side `renderFrameRange()` path, avoiding one Playwright round trip per frame.
|
|
86
|
+
- `--stream-encode` pipes rendered frames directly into local `ffmpeg` with `image2pipe`. Prefer it for final contiguous MP4 renders once QA frames look right.
|
|
87
|
+
- `--skip-duplicates` asks VisualFries deterministic dirty checking to reuse unchanged frames when possible.
|
|
88
|
+
- `--fps <number>` overrides scene FPS.
|
|
89
|
+
- `--audio <path|none>` overrides automatic audio mapping from the local scene audio mix.
|
|
90
|
+
- Without `--audio`, final contiguous renders build a local mixed audio track from active VIDEO/AUDIO components, `audioTracks`, and `settings.audio`.
|
|
91
|
+
- `VISUALFRIES_NODE_MODULES=/path/to/node_modules` lets agents point the CLI at an existing Playwright install.
|
|
92
|
+
- `doctor --json` checks ffmpeg, Vite, Svelte Vite plugin, Playwright, Chromium, and temp directory resolution before an agent starts a render.
|
|
93
|
+
- `catalog --json` lists supported caption presets, cue presets, overlay styles, b-roll motions, transitions, transcript formats, and CLI commands.
|
|
94
|
+
- `validate-cues --json` checks cue file shape, known styles/motions/transitions, and timing before an agent applies cues.
|
|
95
|
+
- `qa` writes `inspect.json`, `screenshots.json`, and sampled `frames/` into one QA directory.
|
|
96
|
+
|
|
97
|
+
Use `init` to create a self-contained agent working directory:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
visualfries init ./video-package \
|
|
101
|
+
--video ./input.mp4 \
|
|
102
|
+
--transcript ./transcript.srt \
|
|
103
|
+
--preset hidden-engine-center \
|
|
104
|
+
--cue-preset hidden-engine-dynamic
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
It creates `scene.json`, `cues.json`, `assets/`, `qa/frames/`, `qa/inspect.json`, `notes.md`, and transcript examples. `cues.json` is generated from the selected cue preset and can be edited before compose/render.
|
|
108
|
+
|
|
109
|
+
Use `compose` when an agent should prepare the scene and, for now, produce a preview MP4 in one command:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
visualfries compose \
|
|
113
|
+
--video ./input.mp4 \
|
|
114
|
+
--transcript ./transcript.srt \
|
|
115
|
+
--cue-preset hidden-engine-dynamic \
|
|
116
|
+
--cues ./cues.json \
|
|
117
|
+
--scene-output ./scene.json \
|
|
118
|
+
--qa-output ./qa/frames \
|
|
119
|
+
--render-mode preview \
|
|
120
|
+
--output ./out.mp4
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`compose` runs the same underlying pipeline as the step-by-step workflow:
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
caption-scene -> optional cue preset -> optional cue file -> inspect -> optional QA screenshots -> render
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Use `apply-cues` when an agent has already planned the visual timeline:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
visualfries preset-cues --duration 45 \
|
|
133
|
+
--preset hidden-engine-dynamic \
|
|
134
|
+
--output ./cues.json
|
|
135
|
+
|
|
136
|
+
visualfries apply-cues ./scene.json \
|
|
137
|
+
--cues ./cues.json \
|
|
138
|
+
--output ./scene.with-cues.json
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Cue files can contain `broll`, `overlays`, and `transitions` arrays:
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"broll": [
|
|
146
|
+
{ "url": "./assets/profile.mp4", "start": 2, "end": 5, "type": "VIDEO" },
|
|
147
|
+
{ "url": "./assets/chart.png", "start": 5, "end": 7, "type": "IMAGE", "motion": "slow-zoom-in" }
|
|
148
|
+
],
|
|
149
|
+
"overlays": [
|
|
150
|
+
{ "text": "LOVE THIS 😍", "start": 0.4, "end": 1.1, "style": "hook-punch" },
|
|
151
|
+
{ "text": "NECK 🤯", "start": 1.1, "end": 1.7, "style": "shock-word" }
|
|
152
|
+
],
|
|
153
|
+
"transitions": [
|
|
154
|
+
{ "time": 2, "style": "dip-to-black" },
|
|
155
|
+
{ "time": 5, "style": "swipe-left", "color": "#04483D" }
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Relative b-roll URLs are resolved relative to the cue file path, so an agent package can keep cues and assets together.
|
|
161
|
+
|
|
162
|
+
`preset-cues` creates a valid starter cue file. It is not meant to replace creative judgment; agents should replace placeholder overlay text and add b-roll paths before the final render.
|
|
163
|
+
|
|
164
|
+
## Node API
|
|
165
|
+
|
|
166
|
+
Use the agent-only subpath for automations and CLIs:
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import { createCaptionScene, inspectScene, normalizeTranscript } from 'visualfries/agent';
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The root `visualfries` export includes the full library surface. Agents should use `visualfries/agent` for captioning and inspection because it avoids browser/Svelte runtime imports.
|
|
173
|
+
|
|
174
|
+
Renderer planning is also agent-safe:
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
import { resolveAgentRenderPlan, requiresDeterministicRender } from 'visualfries/agent';
|
|
178
|
+
|
|
179
|
+
const plan = resolveAgentRenderPlan(scene, { mode: 'final' });
|
|
180
|
+
|
|
181
|
+
if (requiresDeterministicRender(scene)) {
|
|
182
|
+
// Final output needs local deterministic media predecode, not browser video seek.
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
For short-form overlays:
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
import {
|
|
190
|
+
addAgentBrollSequence,
|
|
191
|
+
addAgentTextOverlays,
|
|
192
|
+
addAgentTransitions
|
|
193
|
+
} from 'visualfries/agent';
|
|
194
|
+
|
|
195
|
+
const sceneWithOverlays = addAgentTextOverlays({
|
|
196
|
+
scene,
|
|
197
|
+
overlays: [
|
|
198
|
+
{ text: 'LOVE THIS 😍', start: 0.4, end: 1.1, style: 'pop-label' },
|
|
199
|
+
{ text: 'NECK 🤯', start: 1.1, end: 1.7, style: 'shock-word' }
|
|
200
|
+
]
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const sceneWithBroll = addAgentBrollSequence({
|
|
204
|
+
scene,
|
|
205
|
+
cues: [
|
|
206
|
+
{ url: './broll/profile.mp4', start: 2.0, end: 5.0, type: 'VIDEO' },
|
|
207
|
+
{ url: './broll/chart.png', start: 5.0, end: 7.0, type: 'IMAGE', motion: 'slow-zoom-in' }
|
|
208
|
+
]
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const sceneWithTransitions = addAgentTransitions({
|
|
212
|
+
scene,
|
|
213
|
+
transitions: [
|
|
214
|
+
{ time: 2.0, style: 'dip-to-black' },
|
|
215
|
+
{ time: 5.0, style: 'swipe-left', color: '#04483D' }
|
|
216
|
+
]
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### `caption-scene`
|
|
221
|
+
|
|
222
|
+
Creates a vertical 9:16 scene with:
|
|
223
|
+
|
|
224
|
+
- full-frame video component,
|
|
225
|
+
- subtitle component,
|
|
226
|
+
- scene asset registry,
|
|
227
|
+
- `settings.subtitles.data` populated from transcript JSON.
|
|
228
|
+
|
|
229
|
+
Example:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
visualfries caption-scene \
|
|
233
|
+
--video ./input.mp4 \
|
|
234
|
+
--transcript ./transcript.json \
|
|
235
|
+
--preset hidden-engine-center \
|
|
236
|
+
--output ./scene.json
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Accepted transcript shapes:
|
|
240
|
+
|
|
241
|
+
Plain subtitle files:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
visualfries caption-scene \
|
|
245
|
+
--video ./input.mp4 \
|
|
246
|
+
--transcript ./captions.srt \
|
|
247
|
+
--preset hidden-engine-center \
|
|
248
|
+
--output ./scene.json
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Supported subtitle file formats:
|
|
252
|
+
|
|
253
|
+
- `.srt`
|
|
254
|
+
- `.vtt`
|
|
255
|
+
|
|
256
|
+
Structured JSON:
|
|
257
|
+
|
|
258
|
+
```json
|
|
259
|
+
{
|
|
260
|
+
"segments": [
|
|
261
|
+
{
|
|
262
|
+
"text": "The best content asset is not always a post.",
|
|
263
|
+
"start": 0,
|
|
264
|
+
"end": 2.4,
|
|
265
|
+
"words": [{ "text": "The", "start": 0, "end": 0.12 }]
|
|
266
|
+
}
|
|
267
|
+
]
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
```json
|
|
272
|
+
{
|
|
273
|
+
"words": [
|
|
274
|
+
{ "text": "The", "start": 0, "end": 0.12 },
|
|
275
|
+
{ "text": "best", "start": 0.12, "end": 0.35 }
|
|
276
|
+
]
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Presets
|
|
281
|
+
|
|
282
|
+
Initial caption presets:
|
|
283
|
+
|
|
284
|
+
- `reels-center`
|
|
285
|
+
- `reels-lower`
|
|
286
|
+
- `podcast-clean`
|
|
287
|
+
- `hidden-engine-center`
|
|
288
|
+
|
|
289
|
+
Initial agent overlay styles:
|
|
290
|
+
|
|
291
|
+
- `pop-label` for quick reaction labels above/below captions.
|
|
292
|
+
- `shock-word` for large emphatic keyword reveals.
|
|
293
|
+
- `soft-card` for calmer proof/context callouts.
|
|
294
|
+
- `hook-punch` for the first loud hook label.
|
|
295
|
+
- `proof-pill` for compact proof/credibility beats.
|
|
296
|
+
- `metric-badge` for big numbers and business proof.
|
|
297
|
+
- `danger-crossout` for wrong-path / negative beats.
|
|
298
|
+
- `cta-card` for final choice/question cards.
|
|
299
|
+
|
|
300
|
+
Initial agent b-roll helper:
|
|
301
|
+
|
|
302
|
+
- `addAgentBrollSequence` for timed portrait video/image/GIF cues below captions and overlays.
|
|
303
|
+
- Image cues default to subtle `slow-zoom-in`; use `motion: 'none' | 'slow-zoom-in' | 'slow-zoom-out' | 'drift-up'`.
|
|
304
|
+
|
|
305
|
+
Initial agent transition helper:
|
|
306
|
+
|
|
307
|
+
- `addAgentTransitions` for fast full-frame transition covers at exact beat times.
|
|
308
|
+
- Transition helper covers use animated native SHAPE rectangles.
|
|
309
|
+
- Supported styles: `dip-to-black`, `flash`, `swipe-left`, `swipe-up`.
|
|
310
|
+
|
|
311
|
+
Overlay rules:
|
|
312
|
+
|
|
313
|
+
- Keep the center caption lane free unless the overlay replaces captions for that moment.
|
|
314
|
+
- Use one overlay idea per beat. Split “LOVE THIS” and “NECK” into separate timed cues.
|
|
315
|
+
- Prefer 0.4-1.4 second overlay durations. Longer overlays start feeling like static slides.
|
|
316
|
+
- Render 1-3 QA frames before MP4 encode when a new overlay style is used.
|
|
317
|
+
|
|
318
|
+
See [AGENT_PATTERNS.md](AGENT_PATTERNS.md) for repeatable caption, overlay, b-roll, and QA patterns.
|
|
319
|
+
|
|
320
|
+
## Quality Gates
|
|
321
|
+
|
|
322
|
+
Before a scene is accepted:
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
visualfries validate scene.json
|
|
326
|
+
visualfries inspect scene.json --json
|
|
327
|
+
visualfries inspect scene.json --screenshots --samples 3 --output ./qa/frames --json
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
`inspect` checks schema validity, timeline bounds, missing assets, and subtitle data anchors. With `--screenshots`, it also renders sampled QA frames and returns their paths in the JSON report.
|
|
331
|
+
|
|
332
|
+
Before publishing a rendered video:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
visualfries inspect scene.json --screenshots --samples 3 --output ./qa-frames --json
|
|
336
|
+
visualfries render scene.json --output ./out.mp4
|
|
337
|
+
ffprobe -v error -show_entries stream=codec_type,width,height -of json ./out.mp4
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
For static-heavy scenes, proof screenshots, and overlay sections, the faster render path is:
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
visualfries render scene.json --output ./out.mp4 --skip-duplicates
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Do not use `--skip-duplicates` blindly on complex video-heavy scenes until QA frames look correct.
|
|
347
|
+
|
|
348
|
+
## Complete Agent Production Path
|
|
349
|
+
|
|
350
|
+
VisualFries uses these layers for complete agent-driven production:
|
|
351
|
+
|
|
352
|
+
1. CLI scene creation and validation. Done.
|
|
353
|
+
2. Caption scene generator. Done.
|
|
354
|
+
3. Renderer adapter: `visualfries render scene.json --output out.mp4`. Done for local browser + ffmpeg rendering.
|
|
355
|
+
4. Agent text overlay cues. Done for initial pop/shock/card styles.
|
|
356
|
+
5. Screenshot inspect: `visualfries inspect scene.json --screenshots`. Done.
|
|
357
|
+
6. Agent project scaffold: `visualfries init <dir>`. Done.
|
|
358
|
+
7. Pattern registry for transitions and b-roll layouts. Initial b-roll sequence helper, image motion, transition helper, and cookbook done.
|
|
359
|
+
8. Cue-file CLI application for b-roll/overlays/transitions. Done.
|
|
360
|
+
9. Starter cue presets: `visualfries preset-cues`. Done for `hidden-engine-dynamic` and `captioned-clean`.
|
|
361
|
+
10. One-command agent compose workflow: `visualfries compose`. Done.
|
|
362
|
+
11. Skill/cookbook examples for common agent jobs.
|
|
363
|
+
|
|
364
|
+
The current implementation supports caption-scene creation, validation, inspection, QA frame rendering, MP4 rendering, b-roll cues, text overlays, simple transition cues, cue-file application from the CLI, starter cue presets, and one-command compose.
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# VisualFries Authoring Best Practices
|
|
2
|
+
|
|
3
|
+
VisualFries is an authoring system, not only a schema. A scene is correct only when its semantic components survive validation, runtime evaluation, frame QA, and final rendering.
|
|
4
|
+
|
|
5
|
+
## Default workflow
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
inspect inputs and runtime
|
|
9
|
+
-> choose native semantic components
|
|
10
|
+
-> author scene
|
|
11
|
+
-> validate + inspect structure
|
|
12
|
+
-> frame-QA entry, settled, and exit states
|
|
13
|
+
-> reseek the same frames
|
|
14
|
+
-> render with the deterministic final path
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Validation proves shape. `inspect` proves structural references and timing. Neither proves that a renderer evaluates an animation or effect.
|
|
18
|
+
|
|
19
|
+
## Component decision tree
|
|
20
|
+
|
|
21
|
+
1. Is the visible content typography?
|
|
22
|
+
- Use `TEXT` for headings, metrics, labels, badges, cards, verdicts, CTAs, and other editable words.
|
|
23
|
+
- Use `SUBTITLES` when typography follows transcript timing.
|
|
24
|
+
2. Is it a photo, screenshot, logo, illustration, or supplied bitmap/vector asset?
|
|
25
|
+
- Use `IMAGE` (`GIF` for animated image assets).
|
|
26
|
+
3. Is it moving footage or sound?
|
|
27
|
+
- Use `VIDEO` or `AUDIO`.
|
|
28
|
+
4. Is it independent geometry, decoration, progress, a mask-like layout element, or a transition cover?
|
|
29
|
+
- Use `SHAPE`.
|
|
30
|
+
5. Does typography require a treatment that native `TEXT` cannot render?
|
|
31
|
+
- Rasterization is an explicit fallback. Record the missing native capability and frame-QA the result. Do not rasterize typography merely for convenience.
|
|
32
|
+
|
|
33
|
+
## Native TEXT is mandatory by default
|
|
34
|
+
|
|
35
|
+
Use one `TEXT` component for a normal metric badge such as `881 VIEWS`. It owns its text, background, radius, alignment, outline, shadow, and animation.
|
|
36
|
+
|
|
37
|
+
Good:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"id": "views-badge",
|
|
42
|
+
"type": "TEXT",
|
|
43
|
+
"text": "881 VIEWS",
|
|
44
|
+
"timeline": { "startAt": 0.2, "endAt": 2.8 },
|
|
45
|
+
"order": 10,
|
|
46
|
+
"appearance": {
|
|
47
|
+
"x": 90,
|
|
48
|
+
"y": 150,
|
|
49
|
+
"width": 420,
|
|
50
|
+
"height": 132,
|
|
51
|
+
"horizontalAlign": "center",
|
|
52
|
+
"verticalAlign": "center",
|
|
53
|
+
"background": {
|
|
54
|
+
"enabled": true,
|
|
55
|
+
"color": "#F5D547",
|
|
56
|
+
"target": "wrapper",
|
|
57
|
+
"radius": 24
|
|
58
|
+
},
|
|
59
|
+
"text": {
|
|
60
|
+
"fontFamily": "Montserrat",
|
|
61
|
+
"fontSize": { "value": 72, "unit": "px" },
|
|
62
|
+
"fontWeight": "900",
|
|
63
|
+
"color": "#101820",
|
|
64
|
+
"textAlign": "center",
|
|
65
|
+
"outline": { "enabled": true, "color": "#FFFFFF", "size": 2 },
|
|
66
|
+
"shadow": {
|
|
67
|
+
"enabled": true,
|
|
68
|
+
"color": "#000000",
|
|
69
|
+
"blur": 12,
|
|
70
|
+
"offsetX": 0,
|
|
71
|
+
"offsetY": 4,
|
|
72
|
+
"opacity": 0.55
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Bad:
|
|
80
|
+
|
|
81
|
+
- `881 VIEWS.png` as a full-card `IMAGE`.
|
|
82
|
+
- A rectangle `SHAPE` whose only purpose is to sit behind ordinary `TEXT`.
|
|
83
|
+
- SVG typography generated by a production plan without an explicit native limitation.
|
|
84
|
+
- Assuming schema-valid `clipColor`, dashed outline, or a generic blur must render.
|
|
85
|
+
|
|
86
|
+
A separate `SHAPE` is justified when geometry needs independent timing, motion, progress behavior, or decoration. It is not the default badge background.
|
|
87
|
+
|
|
88
|
+
Directly authored transition geometry is `SHAPE`. `addAgentTransitions` now emits a full-frame animated rectangle rather than the former empty-TEXT compatibility cover.
|
|
89
|
+
|
|
90
|
+
Complete example: [`examples/native-text-metric-badge.json`](examples/native-text-metric-badge.json).
|
|
91
|
+
|
|
92
|
+
## TEXT rendering and compositing
|
|
93
|
+
|
|
94
|
+
`TEXT` uses a wrapper plus an inner text element.
|
|
95
|
+
|
|
96
|
+
- `appearance.background.target: "wrapper"` fills the fixed component box. Use this for badges/cards and for gradient text on a background.
|
|
97
|
+
- `appearance.background.target: "element"` hugs the glyph block and receives legacy `0.22em` padding only when explicit padding is absent.
|
|
98
|
+
- `appearance.text.padding` accepts a non-negative pixel number or `{ top, right, bottom, left }`.
|
|
99
|
+
- `appearance.background.radius` is in pixels.
|
|
100
|
+
- `appearance.text.color` accepts solid colors or gradients. Gradient glyphs use CSS background clipping.
|
|
101
|
+
- `appearance.background.color` accepts solid colors or gradients.
|
|
102
|
+
- Avoid gradient glyphs plus an element-target background: both compete for the inner element's CSS background. Use a wrapper background.
|
|
103
|
+
- Structured outline uses pixel width. Only solid outline is rendered; `dashed`, `dotted`, and `dashArray` remain validation-only.
|
|
104
|
+
- Structured shadow renders color, opacity, x/y offsets, and blur. Legacy named shadow presets remain separate behavior.
|
|
105
|
+
- Wrapper-background TEXT animations target the wrapper, so background and glyph enter together.
|
|
106
|
+
- Plain `TEXT` can target `words`, `lines`, or `chars` through SplitText animations. Transcript-timed active-word behavior belongs on `SUBTITLES`; plain TEXT has no typed word-timing authoring field.
|
|
107
|
+
- `activeWord` and `activeLine` support color/background/weight/scale. `highlightColors` cycles solid colors by active index. If both modes are enabled, `activeWord` wins and validation reports the conflict.
|
|
108
|
+
- Gradient entries in `highlightColors` are diagnosed as unsupported.
|
|
109
|
+
- `clipColor` has no defined runtime semantics. Runtime-aware validation warns before permissive nested parsing can strip it; strict mode rejects it.
|
|
110
|
+
|
|
111
|
+
Browser preview keeps TEXT as HTML above the Pixi canvas. Server/final rendering rasterizes TEXT into Pixi. Risky cross-type stacking and CSS effects require final-render frame QA because preview and final compositing can differ.
|
|
112
|
+
|
|
113
|
+
## Animation contract
|
|
114
|
+
|
|
115
|
+
Runtime-confirmed component animation support:
|
|
116
|
+
|
|
117
|
+
| Component | Animation status | Notes |
|
|
118
|
+
| ------------------- | --------------------- | -------------------------------------------------------------------------------------------- |
|
|
119
|
+
| `TEXT` | Supported | Element or wrapper target; words/lines/chars available. |
|
|
120
|
+
| `SUBTITLES` | Supported with limits | Cue timing works; advanced `out` anchors need visual QA. |
|
|
121
|
+
| `IMAGE` | Supported | Shared Pixi target: relative x/y offsets, opacity, degree rotation, uniform and axis scales. |
|
|
122
|
+
| `VIDEO` | Supported transforms | Same Pixi contract; playback-rate/loop parity remains limited. |
|
|
123
|
+
| `GIF` | Supported transforms | Same Pixi contract; native/final GIF timing parity remains limited. |
|
|
124
|
+
| `SHAPE` | Supported | Regular and progress shapes use a stable outer Pixi target. |
|
|
125
|
+
| `COLOR`, `GRADIENT` | Supported | Canvas fill rendered into Pixi, then the shared transform target. |
|
|
126
|
+
| `AUDIO` | Not applicable | AUDIO has no visual animation target. |
|
|
127
|
+
|
|
128
|
+
For Pixi visuals, animation `x` and `y` are translation offsets relative to authored placement. Pivot/transform origin is fixed at the component center and is not author-configurable. This matches TEXT translation semantics and keeps swipe/drift helpers coherent.
|
|
129
|
+
|
|
130
|
+
Animation rules:
|
|
131
|
+
|
|
132
|
+
- `component.timeline.startAt` offsets the component timeline.
|
|
133
|
+
- Animation-entry `startAt` is relative to component start.
|
|
134
|
+
- `enabled: false` entries do not run.
|
|
135
|
+
- Prefer frame-index-derived times (`frame / fps`) for deterministic QA.
|
|
136
|
+
- For each animation, inspect pre-entry, first-active/mid-entry, settled, and exit frames.
|
|
137
|
+
- Seek forward, backward, and back to the same frame. Same frame must reproduce the same transform/pixels.
|
|
138
|
+
- Destroy/rebuild tests matter; teardown must revert and kill GSAP timelines.
|
|
139
|
+
- SplitText selectors (`words`, `lines`, `chars`, CSS selectors) are TEXT-only. Runtime-aware validation warns (or errors in strict mode) instead of treating Pixi root fallback as support.
|
|
140
|
+
- Animation `setup` steps and `alignTween: "end"|"center"` are not production-safe yet.
|
|
141
|
+
|
|
142
|
+
Complete IMAGE example: [`examples/image-animation.json`](examples/image-animation.json).
|
|
143
|
+
|
|
144
|
+
## Effects and renderer truth
|
|
145
|
+
|
|
146
|
+
Confirmed:
|
|
147
|
+
|
|
148
|
+
- TEXT: structured shadow and solid outline.
|
|
149
|
+
- IMAGE/VIDEO: `layoutSplit` and `fillBackgroundBlur` through the Pixi split-screen path.
|
|
150
|
+
- SHAPE: basic canvas/Pixi geometry and progress shapes.
|
|
151
|
+
|
|
152
|
+
Validation-only or incomplete:
|
|
153
|
+
|
|
154
|
+
- Generic `blur`, `colorAdjustment`, and `rotationRandomizer` are not generally attached to renderers.
|
|
155
|
+
- SHAPE rectangle `cornerRadius` and gradient fill require explicit rendered verification; do not treat schema acceptance as support.
|
|
156
|
+
- Agent transition helpers emit native animated SHAPE rectangles.
|
|
157
|
+
- Same-layer component stacking uses `component.order` (higher order renders later/on top after synchronization). Higher layer order renders above lower layer order in final Pixi composition.
|
|
158
|
+
|
|
159
|
+
## QA checklist
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
visualfries doctor --json
|
|
163
|
+
visualfries catalog --component TEXT --capabilities --json
|
|
164
|
+
visualfries validate scene.json --strict-runtime-support
|
|
165
|
+
visualfries inspect scene.json --json
|
|
166
|
+
visualfries explain scene.json --component views-badge --frame 12 --json
|
|
167
|
+
visualfries parity scene.json --frames 5,12,35 --output qa/parity --json
|
|
168
|
+
|
|
169
|
+
# Render explicit frame windows around authored events.
|
|
170
|
+
visualfries render scene.json --frames-only --from-frame 5 --to-frame 20 --output qa/entry
|
|
171
|
+
visualfries render scene.json --frames-only --from-frame 35 --to-frame 36 --output qa/settled
|
|
172
|
+
|
|
173
|
+
# Final VIDEO/GIF scenes use deterministic-local rendering.
|
|
174
|
+
visualfries render scene.json --stream-encode --output out.mp4
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Uniform three-frame sampling can miss a late or short entrance. Production plans should declare exact `qa.framesAt`; raw scenes should render explicit frame ranges.
|
|
178
|
+
|
|
179
|
+
`parity` captures actual client composition and final server composition, records SHA-256 plus raw and semantic ffmpeg SSIM, evaluates optional class/ROI thresholds from `--rois`, and renders every requested frame forward then backward. It also writes 4× amplified diff rows and a contact sheet. Add `--strict` for CI. The torture-scene baseline passes with zero runtime/resource errors; raw GIF/video decoder noise remains visible and is reported separately from semantic mismatch.
|
|
180
|
+
|
|
181
|
+
## Known open limitations
|
|
182
|
+
|
|
183
|
+
- Visual transform origin is fixed center for Pixi targets; TEXT uses CSS transform ownership. No authorable cross-renderer origin exists.
|
|
184
|
+
- Browser HTML TEXT versus final Pixi TEXT can produce cross-type stacking differences.
|
|
185
|
+
- `clipColor`, gradient highlight palettes, dashed/dotted outline, generic effects, and animation setup steps are unsupported.
|
|
186
|
+
- Native GIF timing and VIDEO/GIF playback controls are not yet preview/final parity guarantees.
|
|
187
|
+
- `componentCenter` and advanced out/align anchors have timing limitations.
|
|
188
|
+
- Radial GRADIENT shape/position currently uses a centered max-radius fallback.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# VisualFries Authoring System Audit
|
|
2
|
+
|
|
3
|
+
Date: 2026-07-12
|
|
4
|
+
|
|
5
|
+
Scope: schema/runtime truth, semantic component selection, visual animation, TEXT compositing, agent diagnostics, preview/final parity, and real frame QA. The current repo is authoritative. The browser/WebGL/MediaBunny worktree was evidence only; browser export was not blindly ported.
|
|
6
|
+
|
|
7
|
+
## Findings, evidence, disposition
|
|
8
|
+
|
|
9
|
+
| Severity | Finding | Evidence | Disposition |
|
|
10
|
+
| -------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
11
|
+
| Critical | Schema accepted animation data for every component although construction attached `AnimationHook` only to TEXT/SUBTITLES/IMAGE. | Base component schema versus `ComponentDirector`; browser regression from the Funeral short. | Fixed for every visual type through a shared Pixi wrapper target; AUDIO remains explicitly nonvisual. Registry/director synchronization tests prevent silent drift. |
|
|
12
|
+
| Critical | COLOR and GRADIENT validated but had no render hook. | `ComponentDirector` returned bare components. | Fixed with canvas fills, Pixi texture/display construction, shared animation target, tests, and frame-QA scene coverage. |
|
|
13
|
+
| High | IMAGE x/y bridge used absolute-center semantics that contradicted TEXT and authored drift/swipe helpers. | `PixiAnimationTarget`, b-roll helpers, transition helpers. | Fixed: all Pixi x/y are placement-relative offsets around a fixed-center outer wrapper. Migration note added. |
|
|
14
|
+
| High | Unsupported runtime fields could validate silently. | Base animation catchalls, permissive nested TEXT parsing, effect schemas. | Fixed materially: capability registry, default warnings, strict runtime-support gate, property/selector/effect/text conflict diagnostics, and pre-parse clipColor detection. Unknown string presets still need deeper static resolution. |
|
|
15
|
+
| High | Production-plan visible typography defaulted to raster/SVG. | Overlay schema/compiler. | Fixed: native TEXT is default; SVG remains explicit documented fallback. |
|
|
16
|
+
| High | Transition helpers used empty TEXT as full-frame geometry. | Agent transition helper and regressions. | Fixed: helpers now emit animated native SHAPE rectangles. |
|
|
17
|
+
| High | Browser HTML TEXT and final Pixi-rasterized TEXT do not share one stacking representation. | `DomManager`, `HtmlTextHook`, `HtmlToCanvasHook`. | Calibrated parity now passes for supported stacking in the torture scene. Arbitrary HTML/Pixi cross-layer interleaving remains an explicit architectural limitation. |
|
|
18
|
+
| Critical | Generated browser harness replaced EventEmitter3 with a shim that discarded listener context, breaking Pixi WebGL prerender and texture updates. | Browser stacks at `BatchRenderer.onPrerender` (`_flushId`) and `Texture.onBaseTextureUpdated` (`noFrame`). | Fixed with a context/once/removal-compatible shim and regression. Browser IMAGE/VIDEO/GIF/SHAPE/COLOR/GRADIENT now render with zero runtime errors. |
|
|
19
|
+
| High | Client seek returned before its asynchronous render and newly attached animation timelines settled. | `TimelineManager.seek`, `RenderManager` queue, sparse browser captures. | Fixed: both renderer paths now render, re-seek after lazy construction, render again, and the harness performs an initialized seek barrier. |
|
|
20
|
+
| High | Preview and final used different hard-coded canvas backgrounds and ignored scene background. | `AppManager` renderer options. | Fixed: both paths use the solid scene background contract; gradient scene backgrounds still require a GRADIENT component. |
|
|
21
|
+
| Medium | Unconfigured system fonts were treated as Google Fonts, creating CORS failures and nondeterministic fallback noise. | Font discovery and SVG text generation. | Fixed: remote font loading is explicit; unconfigured Arial/system families stay local. |
|
|
22
|
+
| Medium | TEXT padding, active scale, and highlight palette fields were absent/ignored. | TEXT schema/builders/highlighter builders. | Fixed: px padding, active word/line scale, solid palette cycling, reset coverage, and deterministic active-word precedence. |
|
|
23
|
+
| Medium | Active-line reset restored background styling instead of glyph color. | `LineHighlighterAnimationBuilder`. | Fixed and asserted explicitly. |
|
|
24
|
+
| Medium | `clipColor` was silently stripped by permissive nested parsing and had no defined semantics. | Runtime/schema search plus parse behavior. | Not invented. Warned by default, rejected by strict gate, documented as open semantic design. |
|
|
25
|
+
| Medium | `visible: false` became true in component state. | Truthy fallback in `_ComponentState`. | Fixed with nullish default and shared wrapper visibility enforcement. |
|
|
26
|
+
| Medium | Same-layer order, component teardown, structured shadow/outline, wrapper transform ownership, and radius units had confirmed defects. | Prior audit source/render tests. | Fixed in the current uncommitted audit set with regression coverage. |
|
|
27
|
+
| High | Scene teardown destroyed Pixi before async component hooks completed, while manager listeners could not be removed by identity. | `SceneBuilder.destroy`, `ComponentsManager.destroy`, `EventManager.on`, `RenderManager`. | Fixed: component/media teardown is awaited before Pixi/DOM destruction; registered callback identities are detached and covered by lifecycle regressions. |
|
|
28
|
+
|
|
29
|
+
## Runtime truth
|
|
30
|
+
|
|
31
|
+
- TEXT/SUBTITLES: HTML animation target; TEXT selectors include container, words, lines, chars, and CSS.
|
|
32
|
+
- IMAGE/VIDEO/GIF/SHAPE/COLOR/GRADIENT: stable outer Pixi target with relative x/y, opacity, degree rotation, scale, scaleX, and scaleY. Pixi selectors support container only.
|
|
33
|
+
- AUDIO: no visual target and no visual animation claim.
|
|
34
|
+
- Visual timing is component-relative; disabled global/list entries do not evaluate; destroy reverts/kills timelines.
|
|
35
|
+
- Pixi transform origin is fixed component center and not authorable.
|
|
36
|
+
- COLOR supports CSS-color canvas fill including alpha. GRADIENT supports linear/radial canvas fills; radial shape/position currently falls back to centered max radius.
|
|
37
|
+
|
|
38
|
+
## TEXT/compositing truth
|
|
39
|
+
|
|
40
|
+
- Paint/style merge order is component background, glyph fill/gradient, then text effects. Active highlight background is a separate element behind split glyphs.
|
|
41
|
+
- Wrapper-target background is preferred for badges/cards and required when both background and glyph are gradients.
|
|
42
|
+
- Element-target gradient background plus gradient glyph fill is diagnosed because both use `background-image` on the inner element.
|
|
43
|
+
- Pixel padding is authorable through `appearance.text.padding`; absent element-target padding keeps the prior `0.22em` fallback.
|
|
44
|
+
- Active word/line scale and solid `highlightColors` work. Active word takes precedence if both modes are enabled. Gradient highlight palettes remain unsupported.
|
|
45
|
+
- Structured solid outline and structured shadow work. Dashed/dotted outline and generic effects remain unsupported/incomplete.
|
|
46
|
+
|
|
47
|
+
## Agent contract
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
visualfries catalog --component TEXT --capabilities --json
|
|
51
|
+
visualfries validate scene.json # compatible load + explicit warnings
|
|
52
|
+
visualfries validate scene.json --strict-runtime-support
|
|
53
|
+
visualfries inspect scene.json --json
|
|
54
|
+
visualfries explain scene.json --component <id> --frame <n> --json
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`explain` seeks the actual browser runtime and reads the chosen HTML/Pixi target; it does not approximate easing in a separate static evaluator.
|
|
58
|
+
|
|
59
|
+
## Verification state
|
|
60
|
+
|
|
61
|
+
- `pnpm exec vitest run`: 64/64 files, 439/439 tests passed.
|
|
62
|
+
- `pnpm run check`: 0 errors; 8 pre-existing docs/accessibility/CSS warnings.
|
|
63
|
+
- `pnpm run build`: passed; `pnpm run package` and standalone `pnpm exec publint` passed.
|
|
64
|
+
- A local runtime-truth torture scene passed strict runtime validation with 0 issues across 9 visual components. Generated QA inputs and outputs are intentionally not committed.
|
|
65
|
+
- Real deterministic final render: 46 frames; frames 0, 9, 18, 30, and 45 visually reviewed.
|
|
66
|
+
- Sparse forward/back/reseek `[18, 30, 18]`: repeated frame 18 matched exactly at SHA-256 `5e30d8dd44ed7cd9ee7ecca8dd6f48dcbf8a48adfd4ac11b47d0eb3d1645636b`.
|
|
67
|
+
- Runtime `explain` at SHAPE frame 18 returned the actual Pixi target and computed x/y/opacity/rotation/scales.
|
|
68
|
+
- Browser/final parity is green on frames 0, 9, 18, 30, and 45. Raw whole-frame SSIM is `0.926262–0.999791`; semantic SSIM is `0.967344–0.999804`. Same-Pixi settled ROIs are `0.995803–1.0` raw, TEXT/SUBTITLES are `0.997588–0.999813`, and zero browser/final runtime or resource errors were recorded.
|
|
69
|
+
- Forward/reverse order `[0,9,18,30,45,45,30,18,9,0]` is stable. Frames 9/18/30/45 are byte-exact in both paths; final frame 0 repeats at SSIM `0.999791` because SVG text rasterization differs by at most three luma levels.
|
|
70
|
+
- A local contact sheet and parity manifest were reviewed across preview, final, and amplified-difference outputs; generated files are intentionally not committed.
|
|
71
|
+
- `git diff --check`: clean. No commit, push, merge, publish, or global-skill modification occurred.
|
|
72
|
+
|
|
73
|
+
## Open limitations
|
|
74
|
+
|
|
75
|
+
1. Browser HTML typography is always above the shared Pixi canvas. Arbitrary TEXT/Pixi cross-layer interleaving can still differ from final ordering; the supported torture composition keeps typography above Pixi visuals.
|
|
76
|
+
2. Native GIF and deterministic ffmpeg decoding differ in palette dithering. Raw GIF ROI reaches `0.539`; 2px semantic SSIM is `0.977`, confirming matching structure/color fields without pretending pixels are identical.
|
|
77
|
+
3. Native browser VIDEO and predecoded final VIDEO use different decode/color paths; current ROI semantic SSIM is `0.939–0.998`. Exact media-frame identity needs a future PTS contract for half-frame starts.
|
|
78
|
+
4. Plain absolute local paths now load, but relative paths are still resolved from process cwd rather than the scene file directory, and assetId-only component sources still need runtime hydration from the asset registry.
|
|
79
|
+
5. Final frame-0 SVG text reseek is visually stable (`0.999791`) but not byte-exact. Other sampled forward/back reseeks are exact.
|
|
80
|
+
6. Transform origin is not authorable across visual renderers.
|
|
81
|
+
7. `clipColor` semantics, gradient highlight palettes, generic effects, dashed/dotted outline, and animation setup steps remain unsupported.
|
|
82
|
+
8. Unknown system animation preset names are still resolved at construction time rather than fully diagnosed statically.
|
|
83
|
+
9. Advanced animation center/end anchors and active-line transcript timing remain limited.
|
|
84
|
+
10. Radial gradient shape/position fields use a centered fallback.
|
|
85
|
+
11. Browser export remains a separate next phase; the MediaBunny spike was not promoted without the higher-priority runtime-truth/parity gates.
|
|
86
|
+
|
|
87
|
+
## Honest readiness score
|
|
88
|
+
|
|
89
|
+
| Dimension | Score | Reason |
|
|
90
|
+
| --- | ---: | --- |
|
|
91
|
+
| Creative speed | 8.3/10 | Semantic helpers, native transitions, and capability discovery remove substantial source-reading. |
|
|
92
|
+
| Runtime trust | 8.2/10 | Strict runtime gate and construction-synchronized registry close the largest silent-success gaps. Unknown preset resolution remains. |
|
|
93
|
+
| Editability | 8.7/10 | Native TEXT defaults, padding/highlighting, SHAPE transitions, and raw JSON output preserve authorability. |
|
|
94
|
+
| Determinism | 8.2/10 | Shared targets and frames 9/18/30/45 reseek exactly; frame-0 SVG text is visually stable rather than byte-exact, and native media timing caveats remain. |
|
|
95
|
+
| Debugging | 8.0/10 | Runtime-backed explain plus stable capability IDs are useful; deeper preset/effect state could improve. |
|
|
96
|
+
| Agent ergonomics | 8.1/10 | Catalog, strict validate, inspect, explain, docs, examples, and release notes form a coherent loop. |
|
|
97
|
+
| Preview/final parity | 8.2/10 | Zero missing visuals/errors; semantic whole-frame and all class ROIs pass. Cross-layer HTML/Pixi ordering and decoder-level pixel differences remain. |
|
|
98
|
+
| Production readiness | 8.0/10 | Agent-visible runtime truth plus green supported-path parity clears the 8/10 bar. Relative/assetId media hydration and arbitrary mixed stacking still block 9/10. |
|