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,55 @@
|
|
|
1
|
+
# Browser WebGL + MediaBunny export spike
|
|
2
|
+
|
|
3
|
+
This spike adds a separate deterministic browser export path. Existing interactive preview and local/cloud FFmpeg rendering are unchanged.
|
|
4
|
+
|
|
5
|
+
MediaBunny is pinned to `1.49.0` for this spike. The newer release available during implementation was less than 14 days old.
|
|
6
|
+
|
|
7
|
+
## Architecture and next slices
|
|
8
|
+
|
|
9
|
+
Current scene transitions are schema data only; existing agent transitions are full-frame overlay components. This milestone therefore keeps normal preview untouched and proves a separate browser export boundary: server-mode Pixi scene canvases → curated WebGL transition canvas → MediaBunny encode/mux. Next reviewable slices are: wire the curated adapter into a frame-index transition manager at the renderer's pre-present seam, adapt MediaBunny decoded samples to the deterministic media provider for real browser video inputs, then add an OPFS/File System Access target for long exports. None requires replacing the FFmpeg/cf-worker fallback.
|
|
10
|
+
|
|
11
|
+
## What it proves
|
|
12
|
+
|
|
13
|
+
- VisualFries/Pixi renders two animated 1080x1920 scenes at exact `frameIndex / 30` timestamps.
|
|
14
|
+
- A curated gl-transitions-compatible WebGL adapter composites `from`, `to`, `progress`, `ratio`, and whitelisted parameters. It ships `fade` and `radial-wipe`; shader compile/link failure falls back to fade.
|
|
15
|
+
- The final WebGL canvas is fed directly to MediaBunny `CanvasSource`. No PNG/JPEG serialization and no websocket frame transport occurs.
|
|
16
|
+
- MediaBunny encodes AVC/H.264 video and AAC audio and muxes MP4. The in-browser audio mix starts at timestamp zero.
|
|
17
|
+
- Every `CanvasSource.add()` is awaited, propagating encoder/writer backpressure. The 10-second demo uses `BufferTarget`; larger integrations can pass a positional `StreamTarget` writable that honors each chunk's `position`.
|
|
18
|
+
|
|
19
|
+
## Run interactively
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm dev
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Open `http://localhost:5173/browser-export-spike`, confirm the AVC + AAC capability report, then click **Render 10-second MP4**.
|
|
26
|
+
|
|
27
|
+
## Produce the checked artifact
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
node scripts/render-browser-export-spike.mjs
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Default output: `artifacts/browser-export-spike/demo.mp4`.
|
|
34
|
+
|
|
35
|
+
Inspect it:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
ffprobe -v error -show_streams -show_format artifacts/browser-export-spike/demo.mp4
|
|
39
|
+
ffmpeg -i artifacts/browser-export-spike/demo.mp4 -vf "select='eq(n,119)+eq(n,120)+eq(n,135)+eq(n,149)+eq(n,150)'" -vsync 0 artifacts/browser-export-spike/frame-%02d.png
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Expected: 300 frames, 10 seconds, 1080x1920 AVC video, AAC stereo audio with `start_time=0`, no blank transition samples, and zero shader fallbacks on a compatible WebGL implementation.
|
|
43
|
+
|
|
44
|
+
## Verified artifact (2026-07-11)
|
|
45
|
+
|
|
46
|
+
- H.264, 1080x1920, 30fps, 300 decoded frames, video duration `10.000000`
|
|
47
|
+
- AAC stereo, 48kHz, audio `start_time=0.000000` (AAC padding extends its reported duration to `10.069333`)
|
|
48
|
+
- First 100ms audio RMS approximately `-34.6 dB`, confirming immediate non-silent audio
|
|
49
|
+
- Transition-window sampled average luma ranged `38.49..50.77`; visual frame inspection found no blank/white frame
|
|
50
|
+
- Four motion samples produced four different decoded-frame hashes
|
|
51
|
+
- Runtime shader fallback count: `0`
|
|
52
|
+
|
|
53
|
+
## Capability and fallback contract
|
|
54
|
+
|
|
55
|
+
The browser path probes the exact requested dimensions and AVC/AAC configuration before work starts. It never silently changes codecs. If unavailable, the structured result names `deterministic-local-ffmpeg`, preserving the existing VisualFries/cf-worker fallback. This milestone does not promise mobile support or arbitrary user GLSL.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# VisualFries Deterministic Renderer
|
|
2
|
+
|
|
3
|
+
VisualFries should own final rendering as a local, first-class capability.
|
|
4
|
+
|
|
5
|
+
## Decision
|
|
6
|
+
|
|
7
|
+
Final output for scenes containing `VIDEO` or `GIF` media must not rely on native browser media seek. Browser media seek is acceptable for preview and QA only.
|
|
8
|
+
|
|
9
|
+
The local deterministic renderer is the source-of-truth path:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
scene.json
|
|
13
|
+
-> collect VIDEO/GIF requirements
|
|
14
|
+
-> predecode media to exact frame images/manifests
|
|
15
|
+
-> browser compositor receives exact frame image for each scene frame
|
|
16
|
+
-> encode frames with ffmpeg
|
|
17
|
+
-> mix/mux audio with ffmpeg
|
|
18
|
+
-> mp4
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
ContentFries cloud workers should eventually become hosted execution wrappers around this VisualFries renderer. They own queues, uploads, progress, retries, chunking, URL signing, auth-specific asset resolution, and deployment concerns, but the render semantics should live in VisualFries.
|
|
22
|
+
|
|
23
|
+
## Preview Contract
|
|
24
|
+
|
|
25
|
+
Preview means cheap and fast:
|
|
26
|
+
|
|
27
|
+
- sampled QA frames,
|
|
28
|
+
- low-resolution or short-range renders,
|
|
29
|
+
- layout inspection,
|
|
30
|
+
- rough browser media playback when explicitly requested.
|
|
31
|
+
|
|
32
|
+
Preview is not a slower copy of final render. If a preview takes longer than final output, it is not a useful preview.
|
|
33
|
+
|
|
34
|
+
## Current Migration State
|
|
35
|
+
|
|
36
|
+
This package now exposes agent-safe render planning:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { resolveAgentRenderPlan, requiresDeterministicRender } from 'visualfries/agent';
|
|
40
|
+
|
|
41
|
+
const plan = resolveAgentRenderPlan(scene, { mode: 'final' });
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The CLI blocks final `VIDEO`/`GIF` renders unless the caller explicitly chooses preview or the legacy escape hatch:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
visualfries render scene.json --render-mode preview --output preview.mp4
|
|
48
|
+
visualfries render scene.json --allow-browser-media-final --output unsafe-experiment.mp4
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The package also includes the first local predecode core:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { prepareLocalDeterministicMedia } from 'visualfries/agent';
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`prepareLocalDeterministicMedia()` resolves `VIDEO`/`GIF` components, computes active frame windows, extracts exact image sequences with local `ffmpeg`, and returns a `visualfries-provider-predecoded` frame manifest. The CLI can inject that manifest into the render page as a deterministic media provider.
|
|
58
|
+
|
|
59
|
+
The CLI also supports image-pipe final encoding:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
visualfries render scene.json --stream-encode --image-format jpg --output out.mp4
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
With `--stream-encode`, rendered frames are written directly into local `ffmpeg` through `image2pipe` instead of first creating a temporary frame sequence. If audio is present, the CLI writes a silent video first and then muxes audio with `-c:v copy`.
|
|
66
|
+
|
|
67
|
+
Audio mixing is local-first as well. The CLI now plans audio from active `VIDEO`/`AUDIO` components, `audioTracks`, and `settings.audio`, prepares each source to 48k stereo FLAC, applies timeline delay/volume, mixes with `amix`, trims to the rendered range, and muxes the mixed track into the final MP4.
|
|
68
|
+
|
|
69
|
+
The same implementation is available as an importable local render boundary:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { renderSceneLocally } from 'visualfries/agent';
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Hosted workers should call this boundary instead of reimplementing frame extraction, browser composition, stream encoding, or audio mixing. The scene passed into this boundary must already contain public, local, or otherwise render-accessible media URLs. URL signing, signed URL refresh, and private asset authorization are wrapper responsibilities, not VisualFries responsibilities. VisualFries must not know how to authenticate ContentFries private assets; if media URLs are not render-accessible, it should fail with useful diagnostics. The package must stay light: `ffmpeg`, Playwright/Chromium, and hosted queue/upload infrastructure are runtime dependencies of the caller, not bundled VisualFries assets.
|
|
76
|
+
|
|
77
|
+
The local renderer owns trim-aware final output. When `scene.settings.trimZones` intersects the requested contiguous frame window, VisualFries renders only the kept frame ranges and concatenates them through the stream encoder. Audio mixing uses the same kept scene-time ranges so video duration and audio duration stay aligned.
|
|
78
|
+
|
|
79
|
+
The same boundary also supports exact single-frame output with `framesOnly: true` and explicit server renderer selection through `serverRendererMode: "canvas" | "webgl"`. Hosted wrappers should pass these options through instead of maintaining separate single-frame or renderer-mode semantics.
|
|
80
|
+
|
|
81
|
+
Frame image quality accepts either browser form (`0..1`) or percent form (`0..100`) and is normalized before the browser render starts. This keeps wrappers from failing later with opaque frame extraction errors when they pass values such as `88`.
|
|
82
|
+
|
|
83
|
+
The next migration slice is making the ContentFries worker call the VisualFries core instead of carrying its own duplicate render semantics.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Next Release Notes (Unreleased)
|
|
2
|
+
|
|
3
|
+
Recommended semver: **0.2.0**. The schemas remain additive/loadable, but confirmed ignored behavior now evaluates and can change pixels. This deserves a pre-1.0 minor release rather than pretending it is a patch-only change.
|
|
4
|
+
|
|
5
|
+
## Added
|
|
6
|
+
|
|
7
|
+
- Typed component capability registry exposed through agent exports and `catalog --component <TYPE> --capabilities --json`.
|
|
8
|
+
- Warning-by-default runtime-support diagnostics and `validate --strict-runtime-support` for agents/CI.
|
|
9
|
+
- Runtime-backed `explain --component <id> --frame <n>` computed target state.
|
|
10
|
+
- Shared deterministic Pixi animation target for IMAGE, VIDEO, GIF, regular/progress SHAPE, COLOR, and GRADIENT.
|
|
11
|
+
- Real COLOR and GRADIENT canvas-to-Pixi render paths.
|
|
12
|
+
- Native TEXT pixel padding, active word/line scale, and solid highlight palette cycling.
|
|
13
|
+
|
|
14
|
+
## Behavior fixes / migration notes
|
|
15
|
+
|
|
16
|
+
- Pixi animation x/y now mean placement-relative translation offsets, matching TEXT and existing swipe/drift helpers. Scenes authored against the short-lived absolute-center IMAGE bridge should subtract the component center from old x/y values.
|
|
17
|
+
- `addAgentTransitions` now emits native SHAPE rectangles instead of background-only empty TEXT.
|
|
18
|
+
- `visible: false` is preserved by component state and shared visual wrappers.
|
|
19
|
+
- Active word wins when active word and active line are both enabled; runtime validation reports the conflict.
|
|
20
|
+
- `clipColor` is diagnosed before permissive parsing can silently discard it. Strict runtime validation rejects it.
|
|
21
|
+
|
|
22
|
+
## Still limited
|
|
23
|
+
|
|
24
|
+
- Transform origin is fixed-center for Pixi visuals and not authorable across renderers.
|
|
25
|
+
- Client HTML TEXT stacking versus final Pixi TEXT remains an architectural parity gap.
|
|
26
|
+
- Native GIF timing and VIDEO/GIF loop/playback-rate parity are not guarantees yet.
|
|
27
|
+
- Gradient highlight palettes, clipColor semantics, generic effects, and advanced setup/anchor behavior remain unsupported.
|
|
28
|
+
- Radial gradient shape/position uses a centered max-radius fallback.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Proposed VisualFries Skill Update (Review Only)
|
|
2
|
+
|
|
3
|
+
This is a repo-local proposal. It does not modify `/Users/lukasgregor/.agents/skills/visualfries/SKILL.md`.
|
|
4
|
+
|
|
5
|
+
Apply these sections to the installed skill only after review/approval.
|
|
6
|
+
|
|
7
|
+
## Replace the agent rule
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
inspect inputs and actual runtime capability
|
|
11
|
+
-> choose native semantic components
|
|
12
|
+
-> author scene JSON
|
|
13
|
+
-> validate + inspect structure
|
|
14
|
+
-> frame-QA entry, settled, exit, and deterministic reseeks
|
|
15
|
+
-> final deterministic render
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Add: Semantic component policy
|
|
19
|
+
|
|
20
|
+
- Visible/editable typography defaults to native `TEXT`, including metrics, labels, badges, verdicts, cards, hooks, and CTAs.
|
|
21
|
+
- Transcript-timed typography uses `SUBTITLES`.
|
|
22
|
+
- A TEXT badge owns its background/gradient/radius/alignment/outline/shadow/animation when those treatments are runtime-supported.
|
|
23
|
+
- Do not create a separate `SHAPE` merely as an ordinary text background. SHAPE is independent geometry, decoration, progress, mask-like layout, or transition content.
|
|
24
|
+
- Transition covers use native animated `SHAPE`; do not use empty TEXT as geometry.
|
|
25
|
+
- Use `IMAGE` for real image assets: photos, screenshots, logos, illustrations, or supplied raster/vector artwork.
|
|
26
|
+
- Raster/SVG typography is an explicit fallback. Record which native limitation requires it and frame-QA it.
|
|
27
|
+
- Production-plan overlays default to native TEXT. Use `renderAs: "SVG"` only for a documented compatibility fallback.
|
|
28
|
+
|
|
29
|
+
## Add: Runtime truth
|
|
30
|
+
|
|
31
|
+
- Validation is not rendering proof.
|
|
32
|
+
- Confirmed visual targets: `TEXT`, `SUBTITLES`, `IMAGE`, `VIDEO`, `GIF`, `SHAPE`, `COLOR`, and `GRADIENT`. AUDIO is nonvisual.
|
|
33
|
+
- Pixi animation `x`/`y` are placement-relative offsets. Pivot is fixed center. Supported properties: x, y, opacity, rotation (degrees), scale, scaleX, scaleY.
|
|
34
|
+
- `clipColor` is unsupported and strict runtime validation rejects it.
|
|
35
|
+
- `appearance.text.padding` supports pixels; absent element-target padding preserves the legacy `0.22em` fallback.
|
|
36
|
+
- Active word/line scale and solid `highlightColors` cycling work. Active word wins when both word and line modes are enabled.
|
|
37
|
+
- Gradient text should use wrapper-target background when a card background is also needed.
|
|
38
|
+
- Browser HTML TEXT and final Pixi-rasterized TEXT can stack differently; verify risky cross-type compositions in final mode.
|
|
39
|
+
|
|
40
|
+
## Replace QA guidance
|
|
41
|
+
|
|
42
|
+
For every animated component:
|
|
43
|
+
|
|
44
|
+
1. Render a pre-entry frame.
|
|
45
|
+
2. Render first-active or mid-entry frame.
|
|
46
|
+
3. Render settled frame.
|
|
47
|
+
4. Render exit frame when applicable.
|
|
48
|
+
5. Seek away and back to the same frame; compare state/pixels.
|
|
49
|
+
|
|
50
|
+
Uniform three-frame QA is not enough for short or late events. Prefer exact production-plan `qa.framesAt` or explicit `--from-frame`/`--to-frame` windows.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
visualfries doctor --json
|
|
54
|
+
visualfries catalog --component TEXT --capabilities --json
|
|
55
|
+
visualfries validate scene.json --strict-runtime-support
|
|
56
|
+
visualfries inspect scene.json --json
|
|
57
|
+
visualfries explain scene.json --component <id> --frame <n> --json
|
|
58
|
+
visualfries parity scene.json --frames <csv> --output qa/parity --json
|
|
59
|
+
visualfries render scene.json --frames-only --from-frame 5 --to-frame 20 --output qa/entry
|
|
60
|
+
visualfries render scene.json --frames-only --from-frame 35 --to-frame 36 --output qa/settled
|
|
61
|
+
visualfries render scene.json --stream-encode --output out.mp4
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Replace the current limitation section
|
|
65
|
+
|
|
66
|
+
- Cookbook depth is not the only remaining gap.
|
|
67
|
+
- Open engine gaps include authorable transform origin, browser/final TEXT stacking parity, clipColor semantics, gradient highlight palettes, generic effects, VIDEO/GIF playback parity, advanced animation anchors/setup, and calibrated preview/final parity metrics.
|
|
68
|
+
- Link the installed skill to `docs/AUTHORING_BEST_PRACTICES.md` in the package/repository.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"broll": [
|
|
3
|
+
{
|
|
4
|
+
"url": "./assets/profile-scroll.mp4",
|
|
5
|
+
"start": 0.2,
|
|
6
|
+
"end": 1.4,
|
|
7
|
+
"type": "VIDEO",
|
|
8
|
+
"fade": 0.18
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"url": "./assets/chart.png",
|
|
12
|
+
"start": 1.4,
|
|
13
|
+
"end": 2.6,
|
|
14
|
+
"type": "IMAGE",
|
|
15
|
+
"motion": "slow-zoom-in"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"overlays": [
|
|
19
|
+
{
|
|
20
|
+
"text": "LOVE THIS \ud83d\ude0d",
|
|
21
|
+
"start": 0.4,
|
|
22
|
+
"end": 1.1,
|
|
23
|
+
"style": "hook-punch"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"text": "NECK \ud83e\udd2f",
|
|
27
|
+
"start": 1.1,
|
|
28
|
+
"end": 1.7,
|
|
29
|
+
"style": "shock-word"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"text": "your move",
|
|
33
|
+
"start": 2.1,
|
|
34
|
+
"end": 2.7,
|
|
35
|
+
"style": "cta-card"
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"transitions": [
|
|
39
|
+
{
|
|
40
|
+
"time": 1.4,
|
|
41
|
+
"style": "dip-to-black"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"time": 2.3,
|
|
45
|
+
"style": "swipe-left",
|
|
46
|
+
"color": "#04483D"
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"segments": [
|
|
3
|
+
{
|
|
4
|
+
"id": "s1",
|
|
5
|
+
"text": "Your content is free therapy for people who will never buy.",
|
|
6
|
+
"start": 0,
|
|
7
|
+
"end": 2.8,
|
|
8
|
+
"words": [
|
|
9
|
+
{ "text": "Your", "start": 0, "end": 0.2 },
|
|
10
|
+
{ "text": "content", "start": 0.2, "end": 0.55 },
|
|
11
|
+
{ "text": "is", "start": 0.55, "end": 0.7 },
|
|
12
|
+
{ "text": "free", "start": 0.7, "end": 1.05 },
|
|
13
|
+
{ "text": "therapy", "start": 1.05, "end": 1.5 },
|
|
14
|
+
{ "text": "for", "start": 1.5, "end": 1.68 },
|
|
15
|
+
{ "text": "people", "start": 1.68, "end": 2.0 },
|
|
16
|
+
{ "text": "who", "start": 2.0, "end": 2.15 },
|
|
17
|
+
{ "text": "will", "start": 2.15, "end": 2.32 },
|
|
18
|
+
{ "text": "never", "start": 2.32, "end": 2.55 },
|
|
19
|
+
{ "text": "buy.", "start": 2.55, "end": 2.8 }
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "image-animation-runtime-proof",
|
|
3
|
+
"version": "2.0",
|
|
4
|
+
"name": "IMAGE animation runtime proof",
|
|
5
|
+
"settings": {
|
|
6
|
+
"width": 1080,
|
|
7
|
+
"height": 1920,
|
|
8
|
+
"duration": 3,
|
|
9
|
+
"fps": 30,
|
|
10
|
+
"backgroundColor": "#111827"
|
|
11
|
+
},
|
|
12
|
+
"assets": [
|
|
13
|
+
{
|
|
14
|
+
"id": "proof-card-asset",
|
|
15
|
+
"type": "IMAGE",
|
|
16
|
+
"url": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='720' height='480'%3E%3Crect width='720' height='480' rx='48' fill='%23F5D547'/%3E%3Ccircle cx='360' cy='240' r='96' fill='%23101820'/%3E%3C/svg%3E"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"layers": [
|
|
20
|
+
{
|
|
21
|
+
"id": "image-layer",
|
|
22
|
+
"name": "Animated image",
|
|
23
|
+
"order": 10,
|
|
24
|
+
"visible": true,
|
|
25
|
+
"muted": false,
|
|
26
|
+
"components": [
|
|
27
|
+
{
|
|
28
|
+
"id": "proof-card",
|
|
29
|
+
"name": "Animated proof card asset",
|
|
30
|
+
"type": "IMAGE",
|
|
31
|
+
"source": {
|
|
32
|
+
"assetId": "proof-card-asset",
|
|
33
|
+
"url": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='720' height='480'%3E%3Crect width='720' height='480' rx='48' fill='%23F5D547'/%3E%3Ccircle cx='360' cy='240' r='96' fill='%23101820'/%3E%3C/svg%3E"
|
|
34
|
+
},
|
|
35
|
+
"timeline": { "startAt": 0.5, "endAt": 3 },
|
|
36
|
+
"visible": true,
|
|
37
|
+
"order": 0,
|
|
38
|
+
"appearance": {
|
|
39
|
+
"x": 180,
|
|
40
|
+
"y": 720,
|
|
41
|
+
"width": 720,
|
|
42
|
+
"height": 480,
|
|
43
|
+
"opacity": 0.9,
|
|
44
|
+
"rotation": 3,
|
|
45
|
+
"scaleX": 1,
|
|
46
|
+
"scaleY": 1
|
|
47
|
+
},
|
|
48
|
+
"animations": {
|
|
49
|
+
"enabled": true,
|
|
50
|
+
"list": [
|
|
51
|
+
{
|
|
52
|
+
"id": "proof-card-enter",
|
|
53
|
+
"name": "Image enter",
|
|
54
|
+
"startAt": 0.15,
|
|
55
|
+
"enabled": true,
|
|
56
|
+
"animation": {
|
|
57
|
+
"id": "proof-card-enter-preset",
|
|
58
|
+
"duration": 0.6,
|
|
59
|
+
"timeline": [
|
|
60
|
+
{
|
|
61
|
+
"tweens": [
|
|
62
|
+
{
|
|
63
|
+
"method": "from",
|
|
64
|
+
"vars": {
|
|
65
|
+
"duration": 0.6,
|
|
66
|
+
"x": -360,
|
|
67
|
+
"opacity": 0,
|
|
68
|
+
"scale": 0.82,
|
|
69
|
+
"rotation": -10,
|
|
70
|
+
"ease": "power3.out"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
"effects": { "enabled": true, "map": {} }
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"transitions": [],
|
|
86
|
+
"audioTracks": []
|
|
87
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "native-text-metric-badge",
|
|
3
|
+
"version": "2.0",
|
|
4
|
+
"name": "Native TEXT metric badge",
|
|
5
|
+
"settings": {
|
|
6
|
+
"width": 1080,
|
|
7
|
+
"height": 1920,
|
|
8
|
+
"duration": 3,
|
|
9
|
+
"fps": 30,
|
|
10
|
+
"backgroundColor": "#151A22"
|
|
11
|
+
},
|
|
12
|
+
"assets": [],
|
|
13
|
+
"layers": [
|
|
14
|
+
{
|
|
15
|
+
"id": "metric-layer",
|
|
16
|
+
"name": "Semantic metric typography",
|
|
17
|
+
"order": 10,
|
|
18
|
+
"visible": true,
|
|
19
|
+
"muted": false,
|
|
20
|
+
"components": [
|
|
21
|
+
{
|
|
22
|
+
"id": "views-badge",
|
|
23
|
+
"name": "881 VIEWS",
|
|
24
|
+
"type": "TEXT",
|
|
25
|
+
"text": "881 VIEWS",
|
|
26
|
+
"timeline": { "startAt": 0.2, "endAt": 3 },
|
|
27
|
+
"visible": true,
|
|
28
|
+
"order": 0,
|
|
29
|
+
"appearance": {
|
|
30
|
+
"x": 90,
|
|
31
|
+
"y": 820,
|
|
32
|
+
"width": 900,
|
|
33
|
+
"height": 220,
|
|
34
|
+
"opacity": 1,
|
|
35
|
+
"rotation": -2,
|
|
36
|
+
"scaleX": 1,
|
|
37
|
+
"scaleY": 1,
|
|
38
|
+
"horizontalAlign": "center",
|
|
39
|
+
"verticalAlign": "center",
|
|
40
|
+
"background": {
|
|
41
|
+
"enabled": true,
|
|
42
|
+
"color": "#F5D547",
|
|
43
|
+
"target": "wrapper",
|
|
44
|
+
"radius": 32
|
|
45
|
+
},
|
|
46
|
+
"text": {
|
|
47
|
+
"fontFamily": "Montserrat",
|
|
48
|
+
"fontSize": { "value": 116, "unit": "px" },
|
|
49
|
+
"fontWeight": "900",
|
|
50
|
+
"lineHeight": { "value": 1, "unit": "em" },
|
|
51
|
+
"color": "#101820",
|
|
52
|
+
"textAlign": "center",
|
|
53
|
+
"textTransform": "uppercase",
|
|
54
|
+
"outline": {
|
|
55
|
+
"enabled": true,
|
|
56
|
+
"color": "#FFFFFF",
|
|
57
|
+
"size": 2,
|
|
58
|
+
"opacity": 1,
|
|
59
|
+
"style": "solid"
|
|
60
|
+
},
|
|
61
|
+
"shadow": {
|
|
62
|
+
"enabled": true,
|
|
63
|
+
"color": "#000000",
|
|
64
|
+
"blur": 16,
|
|
65
|
+
"offsetX": 0,
|
|
66
|
+
"offsetY": 8,
|
|
67
|
+
"opacity": 0.5
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"animations": {
|
|
72
|
+
"enabled": true,
|
|
73
|
+
"list": [
|
|
74
|
+
{
|
|
75
|
+
"id": "views-badge-enter",
|
|
76
|
+
"name": "Badge enter",
|
|
77
|
+
"startAt": 0.1,
|
|
78
|
+
"enabled": true,
|
|
79
|
+
"animation": {
|
|
80
|
+
"id": "views-badge-enter-preset",
|
|
81
|
+
"duration": 0.5,
|
|
82
|
+
"timeline": [
|
|
83
|
+
{
|
|
84
|
+
"tweens": [
|
|
85
|
+
{
|
|
86
|
+
"method": "from",
|
|
87
|
+
"vars": {
|
|
88
|
+
"duration": 0.5,
|
|
89
|
+
"opacity": 0,
|
|
90
|
+
"scale": 0.82,
|
|
91
|
+
"y": 70,
|
|
92
|
+
"ease": "back.out(1.8)"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
"effects": { "enabled": true, "map": {} }
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"transitions": [],
|
|
108
|
+
"audioTracks": []
|
|
109
|
+
}
|