@vanillaskyai/video 0.8.8 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/PUBLIC-API.md +5 -8
- package/dist/{builtin-server-CUYPIDE7.js → builtin-server-W4PLJUZ5.js} +2 -2
- package/dist/{catalog-types-BIhSpOWK.d.ts → catalog-types-WTbLP6Jh.d.ts} +5 -1
- package/dist/chapter-title-YRLIQY3V.js +7 -0
- package/dist/check-runtime.js +5 -14
- package/dist/{chunk-AITKH6QT.js → chunk-2HFO22K2.js} +15 -40
- package/dist/chunk-4YM2M62S.js +13 -0
- package/dist/chunk-4ZJLPHBV.js +684 -0
- package/dist/chunk-77VY4O7A.js +390 -0
- package/dist/{chunk-MMUXVA47.js → chunk-7M56IUUX.js} +9 -8
- package/dist/chunk-7NZOMTAL.js +63 -0
- package/dist/{chunk-2DOLF4QN.js → chunk-AUPC6MDK.js} +12 -14
- package/dist/{chunk-352ZZCET.js → chunk-EGVQODKU.js} +2 -2
- package/dist/{chunk-2USVB3CY.js → chunk-ELVOT2FQ.js} +284 -177
- package/dist/chunk-EWWCQFTI.js +18 -0
- package/dist/{chunk-KT3M7KDL.js → chunk-HKUI5BTB.js} +3 -3
- package/dist/chunk-IIN5M5HW.js +697 -0
- package/dist/{chunk-LMG3GHLL.js → chunk-IQMYK5DX.js} +29 -3
- package/dist/{chunk-OWBT45EN.js → chunk-IR44XKBI.js} +1 -1
- package/dist/{chunk-MXZSDGZQ.js → chunk-NMFDC2W2.js} +4 -6
- package/dist/{chunk-5SLENAJW.js → chunk-PAJ44TFW.js} +1 -2
- package/dist/{chunk-L7QGGKJ2.js → chunk-PDQFQIQW.js} +1 -1
- package/dist/{chunk-WJ6FLKNC.js → chunk-R3XAOMKP.js} +14 -0
- package/dist/{chunk-2OKB27TG.js → chunk-RXTN2CW6.js} +2 -2
- package/dist/{chunk-XWWLKRNU.js → chunk-TVIU23OM.js} +38 -49
- package/dist/chunk-XX4GXKTX.js +35 -0
- package/dist/chunk-Z67Q5KUW.js +16 -0
- package/dist/{chunk-3VRMKFM7.js → chunk-ZDJNFA52.js} +11 -24
- package/dist/cinema-media-C7OUPNSH.js +12 -0
- package/dist/cli.js +18 -9
- package/dist/comparison-GNZOR7MF.js +37 -0
- package/dist/compose-video-TBFTONUC.js +12 -0
- package/dist/editorial-timeline-EMV5335S.js +43 -0
- package/dist/{events-BQ6z264n.d.ts → events-B4YCc4vc.d.ts} +1 -1
- package/dist/index.d.ts +4 -6
- package/dist/index.js +3 -7
- package/dist/key-figure-P37VK425.js +30 -0
- package/dist/{kit-tQnCPMOM.d.ts → kit-DrRpdn0p.d.ts} +2 -2
- package/dist/mobile-message-OF7T62B7.js +50 -0
- package/dist/quote-T6WYLN7A.js +33 -0
- package/dist/react.d.ts +21 -11
- package/dist/react.js +585 -826
- package/dist/scene-video-backdrop-PCTARAAJ.js +7 -0
- package/dist/server.d.ts +7 -8
- package/dist/server.js +179 -84
- package/dist/{system-prompt-RRXIWDDD.js → system-prompt-SYRT5DWM.js} +1 -1
- package/dist/template-catalog.d.ts +392 -16
- package/dist/template-catalog.js +1 -1
- package/dist/templates.d.ts +5 -5
- package/dist/test.d.ts +3 -3
- package/dist/test.js +18 -18
- package/dist/text-stream-LD364KBI.js +9 -0
- package/dist/{types-DWFO6qca.d.ts → types-CdBmNTGD.d.ts} +1 -1
- package/dist/{types-CEh9eUFu.d.ts → types-DdZw4GRQ.d.ts} +17 -48
- package/dist/validate-4OUD2CLX.js +10 -0
- package/docs/architecture.md +1 -1
- package/docs/concepts.md +1 -1
- package/docs/custom-templates.md +13 -28
- package/docs/customization.md +11 -59
- package/docs/getting-started.md +2 -2
- package/docs/immersive-interface.md +3 -4
- package/docs/maintainers/cinematic-migration.md +38 -0
- package/docs/media-and-audio.md +14 -14
- package/docs/motion-and-effects.md +6 -14
- package/docs/persistence.md +3 -3
- package/docs/production.md +11 -9
- package/docs/provider-integration.md +9 -16
- package/docs/reference/design-system.html +1 -1
- package/docs/reference/protocol.md +14 -4
- package/docs/testing.md +1 -1
- package/package.json +6 -3
- package/registry/items/backgrounds.json +1 -1
- package/registry/items/chapterTitle.json +80 -0
- package/registry/items/cinemaMedia.json +136 -0
- package/registry/items/comparison.json +168 -0
- package/registry/items/editorialTimeline.json +172 -0
- package/registry/items/keyFigure.json +162 -0
- package/registry/items/mobileMessage.json +153 -0
- package/registry/items/quote.json +161 -0
- package/registry/items/template-context.json +1 -1
- package/registry/items/theme.json +1 -1
- package/starters/video-chat/README.md +24 -26
- package/starters/video-chat/package.json +1 -1
- package/starters/video-chat/providers/video.ts +6 -5
- package/starters/video-chat/stock.ts +35 -151
- package/styles/fonts/OFL.txt +93 -0
- package/styles/fonts/manifest.json +66 -0
- package/styles/fonts/roboto-v51-cyrillic-ext.woff2 +0 -0
- package/styles/fonts/roboto-v51-cyrillic.woff2 +0 -0
- package/styles/fonts/roboto-v51-greek-ext.woff2 +0 -0
- package/styles/fonts/roboto-v51-greek.woff2 +0 -0
- package/styles/fonts/roboto-v51-latin-ext.woff2 +0 -0
- package/styles/fonts/roboto-v51-latin.woff2 +0 -0
- package/styles/fonts/roboto-v51-math.woff2 +0 -0
- package/styles/fonts/roboto-v51-symbols.woff2 +0 -0
- package/styles/fonts/roboto-v51-vietnamese.woff2 +0 -0
- package/styles/fonts/roboto.css +91 -0
- package/styles/video-chat.css +30 -22
- package/dist/bg-confetti-HITCGLGD.js +0 -89
- package/dist/bg-emoji-VU4UZYZN.js +0 -150
- package/dist/bg-media-L34PDQXJ.js +0 -106
- package/dist/brand-message-FUJ4STFO.js +0 -256
- package/dist/chart-bar-EGPHJATL.js +0 -310
- package/dist/chart-counter-5FFWQNZO.js +0 -306
- package/dist/chart-progress-ring-JMXQLMLC.js +0 -302
- package/dist/chunk-4UNKZEAT.js +0 -3575
- package/dist/chunk-5CDAM24P.js +0 -31
- package/dist/chunk-AOWSXU2K.js +0 -18
- package/dist/chunk-CJ7F2CE6.js +0 -104
- package/dist/chunk-FRN6WKHA.js +0 -185
- package/dist/chunk-G5JPHBX7.js +0 -336
- package/dist/chunk-L5BTTCZV.js +0 -97
- package/dist/chunk-P22HHFDK.js +0 -43
- package/dist/chunk-PP3MCPN4.js +0 -1998
- package/dist/chunk-QAAO7OAY.js +0 -19
- package/dist/chunk-S7HFLYNN.js +0 -35
- package/dist/chunk-W3VDIBGR.js +0 -217
- package/dist/chunk-XGRA2MUV.js +0 -242
- package/dist/chunk-XTOXFMLM.js +0 -105
- package/dist/chunk-YJJC4N4D.js +0 -761
- package/dist/compose-video-2NFH4DZY.js +0 -13
- package/dist/cta-logo-YR7LYUR5.js +0 -212
- package/dist/cta-media-DQJBKUO2.js +0 -221
- package/dist/incoming-call-54KQ7O5A.js +0 -323
- package/dist/infographic-before-after-ROS52GOW.js +0 -460
- package/dist/infographic-feature-list-E7MGUDAN.js +0 -272
- package/dist/infographic-problem-solution-3S6NGO5N.js +0 -343
- package/dist/infographic-stat-row-SYB7AB7H.js +0 -247
- package/dist/infographic-steps-KCE6JWE2.js +0 -406
- package/dist/prompt-input-MHX4O42G.js +0 -239
- package/dist/reaction-SLEGR3BE.js +0 -122
- package/dist/scene-video-backdrop-XFPX4O3I.js +0 -10
- package/dist/showcase-code-2HLAVKBM.js +0 -357
- package/dist/showcase-phone-Q4HEO4LH.js +0 -278
- package/dist/showcase-terminal-DL45LUFG.js +0 -312
- package/dist/showcase-web-2QZO73FZ.js +0 -396
- package/dist/social-conversation-75SD2637.js +0 -695
- package/dist/social-milestone-GEFUQSBF.js +0 -296
- package/dist/social-notification-FJ5VHVLK.js +0 -247
- package/dist/social-review-stack-KXQCKFRP.js +0 -242
- package/dist/social-testimonial-JZ7CHC7S.js +0 -287
- package/dist/social-tweet-UCDXM25F.js +0 -298
- package/dist/text-stream-54LXABJW.js +0 -10
- package/dist/validate-T7GBU2YF.js +0 -8
- package/registry/items/barChart.json +0 -245
- package/registry/items/beforeAfter.json +0 -180
- package/registry/items/bigNumber.json +0 -232
- package/registry/items/brandMessage.json +0 -164
- package/registry/items/cardList.json +0 -214
- package/registry/items/chatMessenger.json +0 -151
- package/registry/items/chatWhatsapp.json +0 -151
- package/registry/items/codeEditor.json +0 -191
- package/registry/items/confetti.json +0 -107
- package/registry/items/ctaLogo.json +0 -167
- package/registry/items/ctaMedia.json +0 -200
- package/registry/items/emojiBurst.json +0 -101
- package/registry/items/incomingCall.json +0 -177
- package/registry/items/media.json +0 -187
- package/registry/items/milestone.json +0 -212
- package/registry/items/notification.json +0 -189
- package/registry/items/phoneMockup.json +0 -261
- package/registry/items/problemSolution.json +0 -193
- package/registry/items/progressRing.json +0 -206
- package/registry/items/promptInput.json +0 -155
- package/registry/items/reaction.json +0 -176
- package/registry/items/reviewStack.json +0 -231
- package/registry/items/steps.json +0 -215
- package/registry/items/terminal.json +0 -219
- package/registry/items/testimonial.json +0 -171
- package/registry/items/tripleStats.json +0 -235
- package/registry/items/tweet.json +0 -210
- package/registry/items/webMockup.json +0 -280
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,48 @@ VanillaSky follows semantic versioning. This changelog begins with the 0.1 beta.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.10.0
|
|
8
|
+
|
|
9
|
+
### Breaking
|
|
10
|
+
|
|
11
|
+
- Remove `focusCards` from the built-in catalog and generated source templates, as requested. Existing callers must replace it with narration over `cinemaMedia`, or an appropriate comparison/timeline when supported by their content. Persisted videos using that ID must be regenerated before playback with the new catalog.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Opening narration advances into the first shot and body. Exact repeated introductory sentences are removed without additional model calls or startup waits.
|
|
16
|
+
- Prefer relevant footage over repeated graphic scenes; use no more than one explanatory overlay in a typical thirty-second answer. Comparison, key figure, quote and timeline can now use optional host-resolved media with a contrast scrim and soft text shadows. Black remains the fallback; chapter titles stay black.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## 0.9.0
|
|
20
|
+
|
|
21
|
+
- Continue video playback with subtitles when native browser speech cannot start, without weakening generated-audio readiness or counting paused time toward the fallback.
|
|
22
|
+
|
|
23
|
+
- Show the spoken opening as a quiet chapter on black when opening media is absent or cannot load. Keep it readable until media or the film is ready, without another generation call.
|
|
24
|
+
|
|
25
|
+
- Package licensed, self-hosted Roboto fallback fonts for the fixed cinematic typography; remove unused promotional template primitives.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Breaking changes
|
|
29
|
+
|
|
30
|
+
- Replace the 28 promotional templates with eight cinematic templates: Full-bleed, Chapter, Focus cards, Timeline, Reach out, Comparison, Quote, and Key figure. Graphics use fixed black backgrounds and white/neutral system typography; only Full-bleed and Reach out accept media.
|
|
31
|
+
- Remove configurable `brand` input and persisted `style.brand`, and remove the public `VideoBrand`, `VideoBrandInput`, `VideoBackground`, and `resolveVideoBrand` exports. Persisted schema is now `0.2` and streaming protocol is `0.6`; older payloads are explicitly rejected.
|
|
32
|
+
- Source-owned templates declare authored reveal, hold and exit minimums. Quote and figure examples remain authoring fixtures and never become factual runtime defaults.
|
|
33
|
+
|
|
34
|
+
Before:
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
<VideoChat options={{ endpoint: "/api/video-chat", brand: { background: "twilight" } }} />
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Adoption
|
|
41
|
+
|
|
42
|
+
Remove brand options and regenerate source-owned templates from the new catalog. Re-author or regenerate saved videos from retained source material; do not rename old IDs or change their version field blindly. See [cinematic migration](docs/maintainers/cinematic-migration.md).
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
<VideoChat options={{ endpoint: "/api/video-chat" }} />
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
|
|
7
49
|
## 0.8.8
|
|
8
50
|
|
|
9
51
|
- Use equal spacing between Sessions, Settings, and Voice controls on mobile and desktop.
|
package/PUBLIC-API.md
CHANGED
|
@@ -131,9 +131,9 @@ playable scenes on an interrupted plan, emitting non-fatal warnings. Explicit
|
|
|
131
131
|
`invalidPartBehavior: "fail"` retains strict generation semantics.
|
|
132
132
|
|
|
133
133
|
- A response accepts `prompt`, `mode`, `orientation`, optional bounded
|
|
134
|
-
`conversation`, `opening`,
|
|
134
|
+
`conversation`, `opening`, and `style`. `opening` is an optional
|
|
135
135
|
prewritten hook from a selected suggestion. The response returns protocol
|
|
136
|
-
`0.
|
|
136
|
+
`0.6` SSE and negotiates `data.video-chat-opening`, which carries the bounded
|
|
137
137
|
6-9 word hook and optional stock-search `keyword` and `fallbackKeyword` before the first scene.
|
|
138
138
|
- The planner produces that opening as the first line of the same model stream
|
|
139
139
|
that produces the scenes. The separate opening-media action resolves its
|
|
@@ -216,7 +216,7 @@ export function App() {
|
|
|
216
216
|
```
|
|
217
217
|
|
|
218
218
|
Pass the same session configuration through `options`, for example
|
|
219
|
-
`<VideoChat options={{ endpoint, headers, templates
|
|
219
|
+
`<VideoChat options={{ endpoint, headers, templates }} />`. `className`
|
|
220
220
|
and `welcomeTitle` are the only shell-level customizations. The stylesheet is
|
|
221
221
|
scoped under `.vanillasky-video-chat` and does not style the host document.
|
|
222
222
|
|
|
@@ -294,10 +294,7 @@ playback is unaffected by either. `onComplete(video)` reports that a streamed
|
|
|
294
294
|
response finished composing; `onPlaybackEnd(video)` reports that the visible
|
|
295
295
|
playhead actually reached the end for either a stream or saved replay.
|
|
296
296
|
|
|
297
|
-
`resolveVideoBrand`
|
|
298
|
-
preset backgrounds, producing the fully resolved `VideoBrand` that `parseVideo`
|
|
299
|
-
requires. Use it when authoring a `Video` by hand rather than copying default
|
|
300
|
-
values into application code.
|
|
297
|
+
Graphic scenes use fixed black backgrounds, white/neutral typography, and the system font stack. `VideoInput.brand`, `VideoStyle.brand`, `VideoBrand`, `VideoBrandInput`, `VideoBackground`, and `resolveVideoBrand` are removed. Media retains natural color. Persisted schema `0.2` and event protocol `0.6` reject earlier versions; changing a version field alone is not a migration.
|
|
301
298
|
|
|
302
299
|
## Template authoring
|
|
303
300
|
|
|
@@ -394,7 +391,7 @@ from `/server` without crossing a React type boundary.
|
|
|
394
391
|
|
|
395
392
|
- A completed `Video` is JSON-serializable and may be stored by the host.
|
|
396
393
|
- Every completed value carries the required storage field
|
|
397
|
-
`schemaVersion: "0.
|
|
394
|
+
`schemaVersion: "0.2"`; it is independent from streaming protocol `0.6`.
|
|
398
395
|
- `parseVideo(value: unknown)` is the strict universal storage boundary. It
|
|
399
396
|
validates the full document and returns a detached, deeply frozen `Video`.
|
|
400
397
|
- JSON serialization remains platform-native; the SDK has no redundant public
|
|
@@ -36,6 +36,10 @@ type TemplateFamily = "Media & motion" | "Data & metrics" | "Product showcase" |
|
|
|
36
36
|
interface TemplateTimingMetadata {
|
|
37
37
|
/** Schema fields whose rendered content may inform a future adaptive duration. */
|
|
38
38
|
readonly contentFields: readonly string[];
|
|
39
|
+
/** Authored motion and uninterrupted reading minimums in seconds. */
|
|
40
|
+
readonly revealSeconds?: number;
|
|
41
|
+
readonly holdSeconds?: number;
|
|
42
|
+
readonly exitSeconds?: number;
|
|
39
43
|
/** How content in contentFields should be measured; no runtime behavior is implied. */
|
|
40
44
|
readonly contentUnit: "words" | "characters" | "items";
|
|
41
45
|
}
|
|
@@ -71,4 +75,4 @@ interface SceneTemplateMetadata {
|
|
|
71
75
|
timing?: TemplateTimingMetadata;
|
|
72
76
|
}
|
|
73
77
|
|
|
74
|
-
export type { SceneTemplateMetadata as S,
|
|
78
|
+
export type { SceneTemplateMetadata as S, TemplateJsonSchema as T, TemplateFamily as a, TemplateTimingMetadata as b, TemplateTransitionTiming as c, TemplateJsonSchemaProperty as d };
|
package/dist/check-runtime.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
VideoFrame
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ELVOT2FQ.js";
|
|
4
4
|
import "./chunk-224QNWRA.js";
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-XWWLKRNU.js";
|
|
5
|
+
import "./chunk-TVIU23OM.js";
|
|
7
6
|
import "./chunk-SPVTJH3F.js";
|
|
8
|
-
import
|
|
9
|
-
resolveVideoBrand
|
|
10
|
-
} from "./chunk-XGRA2MUV.js";
|
|
11
|
-
import "./chunk-WJ6FLKNC.js";
|
|
7
|
+
import "./chunk-R3XAOMKP.js";
|
|
12
8
|
import "./chunk-73NTSFFI.js";
|
|
13
9
|
|
|
14
10
|
// src/cli/check-runtime.ts
|
|
@@ -48,7 +44,7 @@ async function renderTemplateChecks(input) {
|
|
|
48
44
|
for (const orientation of ["portrait", "landscape"]) {
|
|
49
45
|
const [width, height] = orientation === "portrait" ? [1080, 1920] : [1920, 1080];
|
|
50
46
|
const config = {
|
|
51
|
-
schemaVersion: "0.
|
|
47
|
+
schemaVersion: "0.2",
|
|
52
48
|
orientation,
|
|
53
49
|
scenes: [{
|
|
54
50
|
id: "authoring-check",
|
|
@@ -56,12 +52,7 @@ async function renderTemplateChecks(input) {
|
|
|
56
52
|
variables: input.variables,
|
|
57
53
|
timing: { startTime: 0, endTime: input.duration, fixedDuration: input.duration }
|
|
58
54
|
}],
|
|
59
|
-
style: {
|
|
60
|
-
brand: resolveVideoBrand({
|
|
61
|
-
font: "Inter, sans-serif",
|
|
62
|
-
colors: { primary: "#6D5EF5", secondary: "#17122F", foreground: "#FFFFFF" }
|
|
63
|
-
})
|
|
64
|
-
}
|
|
55
|
+
style: {}
|
|
65
56
|
};
|
|
66
57
|
for (const progress of progressPoints) {
|
|
67
58
|
let first;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createVideoSystemPrompt
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PAJ44TFW.js";
|
|
4
4
|
import {
|
|
5
5
|
PACING_PLANNER_RULES
|
|
6
6
|
} from "./chunk-3O7OMMMF.js";
|
|
@@ -15,7 +15,7 @@ function getStandardMediaResolverContract(schema) {
|
|
|
15
15
|
const url = schema.properties.mediaUrl;
|
|
16
16
|
const type = schema.properties.mediaType;
|
|
17
17
|
const allowedTypes = new Set(type?.enum ?? []);
|
|
18
|
-
if (keyword?.format !== "stock-media-keyword" || url?.format !== "uri" || !["photo", "video"
|
|
18
|
+
if (keyword?.format !== "stock-media-keyword" || url?.format !== "uri" || !["photo", "video"].every((value) => allowedTypes.has(value))) {
|
|
19
19
|
return void 0;
|
|
20
20
|
}
|
|
21
21
|
return {
|
|
@@ -26,6 +26,8 @@ function getStandardMediaResolverContract(schema) {
|
|
|
26
26
|
// src/visual-system/catalog/prompt.ts
|
|
27
27
|
function plannerProperty(property) {
|
|
28
28
|
return {
|
|
29
|
+
...property.description == null ? {} : { description: property.description },
|
|
30
|
+
...property.examples == null ? {} : { examples: property.examples.slice(0, 1) },
|
|
29
31
|
...property.type == null ? {} : { type: property.type },
|
|
30
32
|
...property.format == null ? {} : { format: property.format },
|
|
31
33
|
...property.enum == null ? {} : { enum: property.enum },
|
|
@@ -60,10 +62,6 @@ function plannerSchema(schema, exposeMediaKeyword) {
|
|
|
60
62
|
}
|
|
61
63
|
};
|
|
62
64
|
}
|
|
63
|
-
function needsPlannerSchema(schema) {
|
|
64
|
-
const visit = (property) => property.minimum != null || property.maximum != null || property.type === "object" || property.items != null && visit(property.items);
|
|
65
|
-
return Object.values(schema.properties).some(visit);
|
|
66
|
-
}
|
|
67
65
|
function isMediaProperty(property) {
|
|
68
66
|
return property?.format === "uri" || property?.format === "supplied-image" || property?.format === "stock-media-keyword";
|
|
69
67
|
}
|
|
@@ -71,13 +69,6 @@ function requiresAvailableMedia(template) {
|
|
|
71
69
|
const gates = getTemplateSchemaGates(template.schema);
|
|
72
70
|
return (template.schema.required ?? []).some((name) => isMediaProperty(template.schema.properties[name])) || gates.requiredAnyOf.some((group) => group.every((name) => isMediaProperty(template.schema.properties[name])));
|
|
73
71
|
}
|
|
74
|
-
var COMMON_MEDIA_VARIABLES = {
|
|
75
|
-
mediaUrl: "media",
|
|
76
|
-
mediaType: "enum(auto|photo|video|gradient)",
|
|
77
|
-
mediaPoster: "media",
|
|
78
|
-
mediaPosition: "enum(center|top|bottom|left|right)",
|
|
79
|
-
mediaTreatment: "enum(none|subtle|cinematic|text-safe)"
|
|
80
|
-
};
|
|
81
72
|
function plannerCatalog(templates, mediaResolverAvailable) {
|
|
82
73
|
return templates.map((template) => {
|
|
83
74
|
const gates = getTemplateSchemaGates(template.schema);
|
|
@@ -88,23 +79,19 @@ function plannerCatalog(templates, mediaResolverAvailable) {
|
|
|
88
79
|
name === "mediaKeyword" ? "string{2..80}" : templateVariableNotation(property, template.schema.required?.includes(name) === true)
|
|
89
80
|
])
|
|
90
81
|
);
|
|
91
|
-
const usesCommonMedia = Object.entries(COMMON_MEDIA_VARIABLES).every(([name, notation]) => variables[name] === notation);
|
|
92
|
-
if (usesCommonMedia) {
|
|
93
|
-
for (const name of Object.keys(COMMON_MEDIA_VARIABLES)) delete variables[name];
|
|
94
|
-
}
|
|
95
82
|
return {
|
|
96
83
|
id: template.id,
|
|
97
84
|
jobs: template.jobs,
|
|
98
85
|
use: template.useWhen ?? template.description,
|
|
86
|
+
...template.avoidWhen ? { avoid: template.avoidWhen } : {},
|
|
99
87
|
...template.minDuration == null && template.preferredDuration == null ? {} : {
|
|
100
88
|
seconds: [template.minDuration ?? null, template.preferredDuration ?? null]
|
|
101
89
|
},
|
|
102
90
|
...gates.requiresStat ? { requiresStat: true } : {},
|
|
103
91
|
...gates.requiresQuote ? { requiresQuote: true } : {},
|
|
104
92
|
...gates.requiresScreenshot ? { requiresScreenshot: true } : {},
|
|
105
|
-
...gates.requiredAnyOf.length > 0 ? { requiredAnyOf: gates.requiredAnyOf } : {},
|
|
106
|
-
|
|
107
|
-
...usesCommonMedia ? { media: true } : {},
|
|
93
|
+
...gates.requiredAnyOf.length > 0 ? { requiredAnyOf: gates.requiredAnyOf.map((group) => group.filter((name) => name !== "mediaKeyword" || exposeMediaKeyword)) } : {},
|
|
94
|
+
schema: plannerSchema(template.schema, exposeMediaKeyword),
|
|
108
95
|
variables
|
|
109
96
|
};
|
|
110
97
|
});
|
|
@@ -112,24 +99,14 @@ function plannerCatalog(templates, mediaResolverAvailable) {
|
|
|
112
99
|
function createTemplateSystemPrompt(options) {
|
|
113
100
|
const templates = options.kit.listTemplateMetadata().filter((template) => !requiresAvailableMedia(template) || options.suppliedMediaAvailable === true || options.mediaResolverAvailable === true && getStandardMediaResolverContract(template.schema) != null);
|
|
114
101
|
const resolverMediaAvailable = options.mediaResolverAvailable === true && templates.some(({ schema }) => getStandardMediaResolverContract(schema) != null);
|
|
115
|
-
const ids = new Set(templates.map(({ id }) => id));
|
|
116
|
-
const fields = new Set(templates.flatMap(({ schema }) => Object.keys(schema.properties)));
|
|
117
102
|
const basePrompt = createVideoSystemPrompt(options.knowledgeMode, options.narrate === true).split("\n").filter(
|
|
118
103
|
(line) => !line.includes("Never use media, ctaMedia, or reaction as the first generated body template") && // The rule that keeps the opening beat asset-free belongs to the same
|
|
119
104
|
// pair as the one below it: both exist so playback can start without
|
|
120
105
|
// waiting on a provider, and both go when the host owns that wait.
|
|
121
106
|
!(options.mediaOnFirstScene === true && line.includes("The first generated body scene must be asset-free")) && !(resolverMediaAvailable && line.includes("Never expose a loading placeholder or unresolved media keyword"))
|
|
122
107
|
).join("\n");
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
...ids.has("steps") ? ["steps needs two or three unused sequential facts"] : [],
|
|
126
|
-
...ids.has("tripleStats") ? ["tripleStats needs exactly three unused peer values"] : []
|
|
127
|
-
];
|
|
128
|
-
const mediaTemplates = ["media", "ctaMedia", "reaction"].filter((id) => ids.has(id));
|
|
129
|
-
const mediaTemplateNames = mediaTemplates.length === 3 ? "media, ctaMedia, and reaction" : mediaTemplates.join(", ");
|
|
130
|
-
const terminalPayoffs = ["media", "emojiBurst", "confetti"].filter((id) => ids.has(id));
|
|
131
|
-
const terminalPayoffNames = terminalPayoffs.length < 2 ? terminalPayoffs.join("") : `${terminalPayoffs.slice(0, -1).join(", ")}, or ${terminalPayoffs.at(-1)}`;
|
|
132
|
-
const listFields = ["items", "itemEmojis", "steps", "stepEmojis", "problemEmojis", "solutionEmojis"].filter((name) => fields.has(name));
|
|
108
|
+
const mediaTemplates = templates.filter(({ schema }) => getStandardMediaResolverContract(schema) != null).map(({ id }) => id);
|
|
109
|
+
const terminalPayoffs = templates.filter(({ jobs }) => jobs?.includes("payoff")).map(({ id }) => id);
|
|
133
110
|
return [
|
|
134
111
|
basePrompt.trim(),
|
|
135
112
|
options.basePrompt?.trim() ? `
|
|
@@ -139,20 +116,18 @@ ${options.basePrompt.trim()}` : void 0,
|
|
|
139
116
|
"TRUSTED TEMPLATE CATALOG",
|
|
140
117
|
"Only use template IDs from this catalog. Only emit variables declared for the selected template.",
|
|
141
118
|
"Variable notation is type[count]{characters}(options)! where count is list cardinality, characters is the inclusive character count for a string or each string-array item, and ! means required. Omitted ! means optional.",
|
|
142
|
-
`seconds is [minimum, preferred]. media=true adds these optional variables: ${Object.entries(COMMON_MEDIA_VARIABLES).map(([name, notation]) => `${name}:${notation}`).join(", ")}.`,
|
|
143
119
|
"Choose a template only when the permitted factual basis contains every fact it needs. Never invent peer values to complete a chart, comparison, stat set, timeline, or list.",
|
|
144
120
|
...PACING_PLANNER_RULES,
|
|
145
|
-
|
|
146
|
-
"Do not compress a list, sequence, metric set, or comparison into a general-purpose prose field when a specific catalog template can show that structure.",
|
|
121
|
+
"Let narration carry ordinary lists. Use a structured overlay only when a comparison, sequence, exact quote or key figure adds understanding beyond the voice. Prefer relevant full-bleed footage for the rest of the explanation.",
|
|
147
122
|
"If the catalog includes a suitable ask template and the input supplies a grounded CTA or URL, keep that concise action closer as its own final scene instead of folding it into preceding content.",
|
|
148
123
|
"When a grounded CTA or URL is supplied and the catalog contains jobs:[ask], emit that final closer. A brand name may accompany the action but never qualifies as an ask by itself.",
|
|
149
|
-
terminalPayoffs.length > 0 ? `When
|
|
124
|
+
terminalPayoffs.length > 0 ? `When there is no grounded action, end with a concise supported payoff using a suitable template from ${terminalPayoffs.join(", ")}. Do not repeat the hook or invent a CTA.` : void 0,
|
|
150
125
|
"requiresQuote is a hard gate: use those templates only for exact quoted words and attribution present in raw input. Never turn a role, relationship, or summary into speech. requiresScreenshot likewise needs an actual supplied screenshot URL.",
|
|
151
126
|
templates.some(({ schema }) => (schema["x-vanillasky"]?.requiredAnyOf?.length ?? 0) > 0) ? "requiredAnyOf is a hard presence gate: satisfy every listed group with at least one non-empty value." : void 0,
|
|
152
|
-
mediaTemplates.length > 0 && options.mediaOnFirstScene !== true ? `
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
127
|
+
mediaTemplates.length > 0 && options.mediaOnFirstScene !== true ? `The host owns immediate startup; reserve external media templates (${mediaTemplates.join(", ")}) for later beats when an asset-free opening is required.` : void 0,
|
|
128
|
+
"For list and event variables emit actual JSON arrays. Follow each field's content budget; never use pipe-delimited strings or invent entries.",
|
|
129
|
+
resolverMediaAvailable ? "Media-capable scenes may carry mediaKeyword: a literal 2\u20138 word shot description, at most 80 characters. Choose mediaSource=generate for distinctive illustrative shots and mediaSource=stock for common subjects a verified asset can depict. For generated footage, optional shotDirection gives action, framing and continuity separately from the stock query. Keep people, actions and essential details precise. Never broaden an exact identity or action into unrelated atmosphere. Supply a grounded fallbackText where declared. Only the host fills mediaUrl and mediaPoster; never invent them. If no media fits an abstract beat, choose an appropriate graphic template instead." : "Use media only when a supplied asset satisfies the scene. Never invent asset URLs. Otherwise choose a grounded graphic template.",
|
|
130
|
+
"When the catalog offers media, make relevant footage the default. For a typical 30-second answer use at most one structured explanatory overlay plus an optional brief chapter opening. Do not chain graphic-only beats when honest media is available. Reuse suitable supplied media behind overlays with optional media fields; retain black when no relevant asset exists. Never invent a stock match or spend beyond host generation limits.",
|
|
156
131
|
"Catalog guidance describes composition; it is not a factual source and must never replace the permitted factual basis.",
|
|
157
132
|
JSON.stringify(plannerCatalog(templates, resolverMediaAvailable)),
|
|
158
133
|
// Last, because the catalogue is thousands of tokens of per-scene field
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/visual-system/scene-templates/editorial-typography.ts
|
|
2
|
+
var editorialFont = '-apple-system, BlinkMacSystemFont, "Helvetica Neue", Roboto, Arial, sans-serif';
|
|
3
|
+
var fade = (value) => {
|
|
4
|
+
const t = Math.max(0, Math.min(1, value));
|
|
5
|
+
return t * t * (3 - 2 * t);
|
|
6
|
+
};
|
|
7
|
+
var editorialLabel = (unit) => ({ fontSize: unit * 0.042, fontWeight: 400, color: "#b7b7bc", lineHeight: 1.25 });
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
editorialFont,
|
|
11
|
+
fade,
|
|
12
|
+
editorialLabel
|
|
13
|
+
};
|