visualfries 0.1.10115 → 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.
Files changed (139) hide show
  1. package/README.md +122 -0
  2. package/bin/visualfries.js +1570 -0
  3. package/dist/DIContainer.d.ts +2 -1
  4. package/dist/DIContainer.js +16 -5
  5. package/dist/SceneBuilder.svelte.d.ts +70 -1
  6. package/dist/SceneBuilder.svelte.js +96 -29
  7. package/dist/agent/audioMixer.d.ts +34 -0
  8. package/dist/agent/audioMixer.js +308 -0
  9. package/dist/agent/broll.d.ts +35 -0
  10. package/dist/agent/broll.js +226 -0
  11. package/dist/agent/capabilities.d.ts +34 -0
  12. package/dist/agent/capabilities.js +246 -0
  13. package/dist/agent/captionScene.d.ts +23 -0
  14. package/dist/agent/captionScene.js +204 -0
  15. package/dist/agent/catalog.d.ts +24 -0
  16. package/dist/agent/catalog.js +67 -0
  17. package/dist/agent/cueFiles.d.ts +54 -0
  18. package/dist/agent/cueFiles.js +219 -0
  19. package/dist/agent/cuePresets.d.ts +7 -0
  20. package/dist/agent/cuePresets.js +50 -0
  21. package/dist/agent/deterministicMedia.d.ts +61 -0
  22. package/dist/agent/deterministicMedia.js +303 -0
  23. package/dist/agent/index.d.ts +18 -0
  24. package/dist/agent/index.js +18 -0
  25. package/dist/agent/inspectScene.d.ts +36 -0
  26. package/dist/agent/inspectScene.js +139 -0
  27. package/dist/agent/localRender.d.ts +82 -0
  28. package/dist/agent/localRender.js +702 -0
  29. package/dist/agent/overlays.d.ts +40 -0
  30. package/dist/agent/overlays.js +325 -0
  31. package/dist/agent/productionPlan.d.ts +131 -0
  32. package/dist/agent/productionPlan.js +322 -0
  33. package/dist/agent/renderPlan.d.ts +27 -0
  34. package/dist/agent/renderPlan.js +68 -0
  35. package/dist/agent/renderRanges.d.ts +24 -0
  36. package/dist/agent/renderRanges.js +73 -0
  37. package/dist/agent/runtimeSupport.d.ts +19 -0
  38. package/dist/agent/runtimeSupport.js +192 -0
  39. package/dist/agent/streamingEncoder.d.ts +31 -0
  40. package/dist/agent/streamingEncoder.js +208 -0
  41. package/dist/agent/transcripts.d.ts +29 -0
  42. package/dist/agent/transcripts.js +146 -0
  43. package/dist/agent/transitions.d.ts +20 -0
  44. package/dist/agent/transitions.js +169 -0
  45. package/dist/animations/PixiAnimationTarget.d.ts +29 -0
  46. package/dist/animations/PixiAnimationTarget.js +63 -0
  47. package/dist/animations/builders/LineHighlighterAnimationBuilder.js +20 -3
  48. package/dist/animations/builders/WordHighlighterAnimationBuilder.js +15 -2
  49. package/dist/browser/browserExport.d.ts +73 -0
  50. package/dist/browser/browserExport.js +180 -0
  51. package/dist/browser/glTransitions.d.ts +37 -0
  52. package/dist/browser/glTransitions.js +261 -0
  53. package/dist/browser/index.d.ts +3 -0
  54. package/dist/browser/index.js +3 -0
  55. package/dist/browser/mediaDecode.d.ts +31 -0
  56. package/dist/browser/mediaDecode.js +152 -0
  57. package/dist/builders/PixiComponentBuilder.d.ts +6 -0
  58. package/dist/builders/PixiComponentBuilder.js +12 -0
  59. package/dist/builders/_ComponentState.svelte.d.ts +7 -5
  60. package/dist/builders/_ComponentState.svelte.js +29 -15
  61. package/dist/builders/html/StyleBuilder.js +9 -8
  62. package/dist/builders/html/TextComponentHtmlBuilder.js +4 -2
  63. package/dist/builders/html/processors/AppearanceStyleProcessor.js +1 -1
  64. package/dist/builders/html/processors/TextAppearanceStyleProcessor.js +7 -0
  65. package/dist/builders/html/processors/TextEffectsStyleProcessor.js +32 -13
  66. package/dist/commands/ReplaceSourceOnTimeCommand.js +9 -1
  67. package/dist/commands/SeekCommand.js +19 -6
  68. package/dist/components/AnimatedGIF.d.ts +3 -0
  69. package/dist/components/AnimatedGIF.js +28 -1
  70. package/dist/components/Component.svelte.d.ts +5 -5
  71. package/dist/components/Component.svelte.js +29 -13
  72. package/dist/components/ComponentContext.svelte.js +68 -23
  73. package/dist/components/hooks/AnimationHook.js +1 -1
  74. package/dist/components/hooks/CanvasFillHook.d.ts +12 -0
  75. package/dist/components/hooks/CanvasFillHook.js +75 -0
  76. package/dist/components/hooks/DeterministicMediaFrameHook.js +3 -0
  77. package/dist/components/hooks/HtmlTextHook.js +11 -3
  78. package/dist/components/hooks/HtmlToCanvasHook.js +8 -25
  79. package/dist/components/hooks/MediaHook.js +172 -47
  80. package/dist/components/hooks/MediaSeekingHook.js +138 -88
  81. package/dist/components/hooks/PixiGifHook.js +4 -4
  82. package/dist/components/hooks/PixiSplitScreenDisplayObjectHook.d.ts +3 -0
  83. package/dist/components/hooks/PixiSplitScreenDisplayObjectHook.js +85 -8
  84. package/dist/components/hooks/PixiVideoTextureHook.js +10 -4
  85. package/dist/components/hooks/PixiVisualTransformHook.d.ts +16 -0
  86. package/dist/components/hooks/PixiVisualTransformHook.js +102 -0
  87. package/dist/components/hooks/SubtitlesHook.js +48 -24
  88. package/dist/components/hooks/VerifyMediaHook.js +2 -2
  89. package/dist/directors/ComponentDirector.d.ts +1 -0
  90. package/dist/directors/ComponentDirector.js +41 -8
  91. package/dist/factories/SceneBuilderFactory.d.ts +3 -0
  92. package/dist/factories/SceneBuilderFactory.js +6 -0
  93. package/dist/fonts/fontDiscovery.js +12 -1
  94. package/dist/layers/Layer.svelte.d.ts +54 -0
  95. package/dist/layers/Layer.svelte.js +2 -25
  96. package/dist/managers/AppManager.svelte.d.ts +12 -0
  97. package/dist/managers/AppManager.svelte.js +180 -8
  98. package/dist/managers/ComponentsManager.svelte.d.ts +7 -7
  99. package/dist/managers/ComponentsManager.svelte.js +29 -15
  100. package/dist/managers/DeterministicMediaManager.d.ts +6 -0
  101. package/dist/managers/DeterministicMediaManager.js +57 -3
  102. package/dist/managers/EventManager.js +3 -1
  103. package/dist/managers/LayersManager.svelte.d.ts +54 -0
  104. package/dist/managers/RenderManager.d.ts +5 -0
  105. package/dist/managers/RenderManager.js +67 -21
  106. package/dist/managers/StateManager.svelte.d.ts +56 -0
  107. package/dist/managers/StateManager.svelte.js +60 -58
  108. package/dist/managers/SubtitlesManager.svelte.js +1 -3
  109. package/dist/managers/TimeManager.svelte.d.ts +4 -0
  110. package/dist/managers/TimeManager.svelte.js +23 -7
  111. package/dist/schemas/runtime/deterministic.d.ts +3 -0
  112. package/dist/schemas/runtime/deterministic.js +5 -1
  113. package/dist/schemas/runtime/types.d.ts +36 -15
  114. package/dist/schemas/scene/components.d.ts +126 -0
  115. package/dist/schemas/scene/components.js +11 -0
  116. package/dist/schemas/scene/core.d.ts +109 -10
  117. package/dist/schemas/scene/core.js +1 -1
  118. package/dist/utils/mediaWindow.d.ts +13 -0
  119. package/dist/utils/mediaWindow.js +25 -0
  120. package/dist/utils/svgGenerator.js +1 -1
  121. package/dist/utils/timelineWindow.d.ts +2 -0
  122. package/dist/utils/timelineWindow.js +7 -0
  123. package/dist/utils/utils.js +2 -4
  124. package/docs/AGENT_PATTERNS.md +243 -0
  125. package/docs/AGENT_WORKFLOW.md +364 -0
  126. package/docs/AUTHORING_BEST_PRACTICES.md +188 -0
  127. package/docs/AUTHORING_SYSTEM_AUDIT.md +98 -0
  128. package/docs/BROWSER_EXPORT_SPIKE.md +55 -0
  129. package/docs/DETERMINISTIC_RENDERER.md +83 -0
  130. package/docs/NEXT_RELEASE.md +28 -0
  131. package/docs/PROPOSED_VISUALFRIES_SKILL.md +68 -0
  132. package/docs/examples/agent-cues.json +49 -0
  133. package/docs/examples/agent-transcript.json +23 -0
  134. package/docs/examples/agent-transcript.srt +7 -0
  135. package/docs/examples/agent-transcript.vtt +7 -0
  136. package/docs/examples/image-animation.json +87 -0
  137. package/docs/examples/native-text-metric-badge.json +109 -0
  138. package/package.json +133 -100
  139. package/skills/visualfries/SKILL.md +328 -0
@@ -0,0 +1,2 @@
1
+ export declare const TIMELINE_BOUNDARY_EPSILON = 1e-7;
2
+ export declare function isTimeWithinTimeline(currentTime: number, startAt: number, endAt: number, epsilon?: number): boolean;
@@ -0,0 +1,7 @@
1
+ export const TIMELINE_BOUNDARY_EPSILON = 1e-7;
2
+ export function isTimeWithinTimeline(currentTime, startAt, endAt, epsilon = TIMELINE_BOUNDARY_EPSILON) {
3
+ if (endAt - startAt <= epsilon) {
4
+ return currentTime >= startAt - epsilon && currentTime <= endAt + epsilon;
5
+ }
6
+ return currentTime >= startAt - epsilon && currentTime < endAt - epsilon;
7
+ }
@@ -41,9 +41,7 @@ export const buildCharactersListFromComponentsAndSubtitles = function (layers, s
41
41
  const c = component;
42
42
  const text = c.text;
43
43
  if (text) {
44
- // Use Array.from to properly handle multi-codepoint characters (emojis, etc.)
45
- // This prevents splitting emojis into unpaired surrogates
46
- const textList = Array.from(text);
44
+ const textList = text.split('');
47
45
  const missingChars = textList.filter((char) => {
48
46
  // Check if the character is not whitespace, not in the characters list,
49
47
  // is a Unicode letter or number, and is NOT an emoji
@@ -108,7 +106,7 @@ export const setPlacementAndOpacity = function (obj, c) {
108
106
  obj.y = config.y;
109
107
  obj.width = config.width;
110
108
  obj.height = config.height;
111
- obj.alpha = config.opacity || 1;
109
+ obj.alpha = config.opacity ?? 1;
112
110
  if (config.rotation) {
113
111
  obj.angle = config.rotation;
114
112
  }
@@ -0,0 +1,243 @@
1
+ # VisualFries Agent Patterns
2
+
3
+ Reusable building blocks for agents that need short-form videos without writing raw scene JSON from scratch.
4
+
5
+ ## New Agent Package
6
+
7
+ Use when starting a self-contained work folder:
8
+
9
+ ```bash
10
+ visualfries init ./video-package \
11
+ --video ./input.mp4 \
12
+ --transcript ./transcript.srt \
13
+ --preset hidden-engine-center \
14
+ --cue-preset hidden-engine-dynamic
15
+ ```
16
+
17
+ Generated structure:
18
+
19
+ ```text
20
+ video-package/
21
+ scene.json
22
+ cues.json
23
+ assets/
24
+ qa/
25
+ inspect.json
26
+ frames/
27
+ notes.md
28
+ transcript.example.json
29
+ ```
30
+
31
+ `cues.json` is generated from the selected cue preset and should be treated as the visual timeline map for the video.
32
+
33
+ ## Captioned Video
34
+
35
+ Use when the base asset already contains the main story or voiceover.
36
+
37
+ Fastest preview path:
38
+
39
+ ```bash
40
+ visualfries compose \
41
+ --video ./input.mp4 \
42
+ --transcript ./transcript.srt \
43
+ --cue-preset hidden-engine-dynamic \
44
+ --cues ./cues.json \
45
+ --scene-output ./scene.json \
46
+ --qa-output ./qa/frames \
47
+ --render-mode preview \
48
+ --output ./out.mp4
49
+ ```
50
+
51
+ Use `compose` for routine agent previews. Use the step-by-step commands when debugging a scene. Final output for scenes with `VIDEO` or `GIF` components uses the local deterministic renderer path, which predecodes media into exact frame images before the browser compositor sees the scene. Browser media rendering is intentionally treated as preview-only.
52
+
53
+ ```bash
54
+ visualfries caption-scene \
55
+ --video ./input.mp4 \
56
+ --transcript ./transcript.srt \
57
+ --preset hidden-engine-center \
58
+ --output ./scene.json
59
+ ```
60
+
61
+ `--transcript` accepts JSON, SRT, or VTT. Prefer SRT/VTT when the agent already has timed subtitles from another tool.
62
+
63
+ Then QA:
64
+
65
+ ```bash
66
+ visualfries inspect ./scene.json --screenshots --samples 3 --output ./qa/frames --json
67
+ ```
68
+
69
+ ## Cue File Application
70
+
71
+ Use when an agent has a timeline map and should not write custom JavaScript.
72
+
73
+ ```bash
74
+ visualfries preset-cues --duration 45 \
75
+ --preset hidden-engine-dynamic \
76
+ --output ./cues.json
77
+
78
+ visualfries apply-cues ./scene.json \
79
+ --cues ./cues.json \
80
+ --output ./scene.with-cues.json
81
+ ```
82
+
83
+ Cue file:
84
+
85
+ ```json
86
+ {
87
+ "broll": [
88
+ { "url": "./assets/profile-scroll.mp4", "start": 2, "end": 5, "type": "VIDEO" }
89
+ ],
90
+ "overlays": [
91
+ { "text": "LOVE THIS 😍", "start": 0.4, "end": 1.1, "style": "hook-punch" },
92
+ { "text": "your move", "start": 41.5, "end": 43, "style": "cta-card" }
93
+ ],
94
+ "transitions": [
95
+ { "time": 2, "style": "dip-to-black" }
96
+ ]
97
+ }
98
+ ```
99
+
100
+ Use this as the normal agent path:
101
+
102
+ ```text
103
+ compose
104
+ ```
105
+
106
+ For debugging:
107
+
108
+ ```text
109
+ caption-scene -> preset-cues -> edit cues -> apply-cues -> inspect --screenshots -> render
110
+ ```
111
+
112
+ Available starter presets:
113
+
114
+ - `hidden-engine-dynamic`: cue skeleton for 40-60s story-driven shorts with hook/proof/mechanism/choice/CTA overlay beats.
115
+ - `captioned-clean`: minimal transition cues for caption-first videos.
116
+
117
+ ## Timed Text Overlays
118
+
119
+ Use for quick reaction beats, keyword shocks, proof callouts, and hook emphasis.
120
+
121
+ ```ts
122
+ import { addAgentTextOverlays } from 'visualfries/agent';
123
+
124
+ const withOverlays = addAgentTextOverlays({
125
+ scene,
126
+ overlays: [
127
+ { text: 'LOVE THIS 😍', start: 0.4, end: 1.1, style: 'pop-label' },
128
+ { text: 'NECK 🤯', start: 1.1, end: 1.7, style: 'shock-word' },
129
+ { text: '1M PROFIT', start: 2.0, end: 3.0, style: 'metric-badge' }
130
+ ]
131
+ });
132
+ ```
133
+
134
+ Overlay styles:
135
+
136
+ - `hook-punch`: loud yellow hook label for the first second.
137
+ - `shock-word`: large keyword reveal.
138
+ - `metric-badge`: big number/proof badge.
139
+ - `proof-pill`: smaller credibility/proof pill.
140
+ - `danger-crossout`: negative beat / wrong path callout.
141
+ - `cta-card`: final question or choice card.
142
+ - `pop-label`: generic fast reaction label.
143
+ - `soft-card`: calmer context card.
144
+
145
+ Rules:
146
+
147
+ - one overlay idea per beat,
148
+ - 0.4-1.4 seconds per overlay,
149
+ - keep captions readable,
150
+ - render sampled screenshots before final MP4.
151
+
152
+ ## B-roll Sequence
153
+
154
+ Use when an agent has portrait stock footage, generated images, screen recordings, or proof visuals.
155
+
156
+ ```ts
157
+ import { addAgentBrollSequence } from 'visualfries/agent';
158
+
159
+ const withBroll = addAgentBrollSequence({
160
+ scene,
161
+ cues: [
162
+ { url: './broll/profile.mp4', start: 2.0, end: 5.0, type: 'VIDEO' },
163
+ { url: './broll/chart.png', start: 5.0, end: 7.0, type: 'IMAGE', motion: 'slow-zoom-in' }
164
+ ]
165
+ });
166
+ ```
167
+
168
+ Layer defaults:
169
+
170
+ - b-roll layer order: `5`
171
+ - captions layer from `caption-scene`: `10`
172
+ - text overlay layer: `90`
173
+
174
+ This means b-roll naturally replaces/augments the base media while captions and overlays stay visible.
175
+
176
+ Image motion:
177
+
178
+ - `slow-zoom-in` default for images,
179
+ - `slow-zoom-out`,
180
+ - `drift-up`,
181
+ - `none`.
182
+
183
+ ## Beat Transitions
184
+
185
+ Use when a hard cut between b-roll/avatar/proof visuals needs a small cover at an exact beat.
186
+
187
+ ```ts
188
+ import { addAgentTransitions } from 'visualfries/agent';
189
+
190
+ const withTransitions = addAgentTransitions({
191
+ scene,
192
+ transitions: [
193
+ { time: 2.0, style: 'dip-to-black' },
194
+ { time: 5.0, style: 'swipe-left', color: '#04483D' }
195
+ ]
196
+ });
197
+ ```
198
+
199
+ Available styles:
200
+
201
+ - `dip-to-black` for invisible cuts,
202
+ - `flash` for punchy hook beats,
203
+ - `swipe-left` for editorial movement,
204
+ - `swipe-up` for vertical short-form movement.
205
+
206
+ Keep transition durations short, usually `0.18-0.32s`. Overusing them makes the edit feel templated.
207
+
208
+ ## Agent QA Loop
209
+
210
+ For every non-trivial scene:
211
+
212
+ ```bash
213
+ visualfries doctor --json
214
+ visualfries catalog --json
215
+ visualfries validate-cues ./cues.json --duration 45 --json
216
+ visualfries validate ./scene.json
217
+ visualfries qa ./scene.json --output ./qa
218
+ visualfries render ./scene.json --render-mode preview --output ./preview.mp4
219
+ ffprobe -v error -show_entries stream=codec_type,width,height -of json ./preview.mp4
220
+ ```
221
+
222
+ If `visualfries render` blocks a final VIDEO/GIF scene, that is expected. Do not bypass it for shipped output. The scene needs deterministic predecoded media frames before final encode.
223
+
224
+ For final contiguous MP4 renders, prefer streaming encode after QA:
225
+
226
+ ```bash
227
+ visualfries render ./scene.with-cues.json \
228
+ --stream-encode \
229
+ --image-format jpg \
230
+ --output ./out.mp4
231
+ ```
232
+
233
+ This avoids writing every final frame to disk before encode.
234
+
235
+ For static-heavy agent videos, add `--skip-duplicates` after QA:
236
+
237
+ ```bash
238
+ visualfries render ./scene.json --output ./out.mp4 --skip-duplicates
239
+ ```
240
+
241
+ The CLI uses VisualFries `renderFrameRange()` for contiguous frame ranges. Sparse QA screenshots still use direct sampled frame renders.
242
+
243
+ If screenshot samples show overlap, fix the scene JSON or cue timing before encoding the full video.
@@ -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.