@vanillaskyai/video 0.9.0 → 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 +12 -0
- package/dist/{builtin-server-HW6HGXCZ.js → builtin-server-W4PLJUZ5.js} +2 -2
- package/dist/check-runtime.js +2 -2
- package/dist/{chunk-UDIODEDK.js → chunk-224QNWRA.js} +5 -1
- package/dist/{chunk-OR52UMSF.js → chunk-2HFO22K2.js} +2 -1
- package/dist/{chunk-MXEYPK7M.js → chunk-4ZJLPHBV.js} +194 -62
- package/dist/{chunk-3ZTEFJIR.js → chunk-ELVOT2FQ.js} +1 -1
- package/dist/{chunk-LH4BPALA.js → chunk-IIN5M5HW.js} +194 -61
- package/dist/{chunk-MQILEEXC.js → chunk-IR44XKBI.js} +1 -1
- package/dist/{chunk-G7IZBBWF.js → chunk-NMFDC2W2.js} +3 -10
- package/dist/chunk-XX4GXKTX.js +35 -0
- package/dist/chunk-Z67Q5KUW.js +16 -0
- package/dist/{cinema-media-YQHSIFDA.js → cinema-media-C7OUPNSH.js} +3 -2
- package/dist/cli.js +3 -3
- package/dist/{comparison-RZMMHZR2.js → comparison-GNZOR7MF.js} +14 -4
- package/dist/{editorial-timeline-OZX7OS6G.js → editorial-timeline-EMV5335S.js} +10 -3
- package/dist/key-figure-P37VK425.js +30 -0
- package/dist/{mobile-message-UZUPIKHD.js → mobile-message-OF7T62B7.js} +3 -2
- package/dist/{preload-media-CFTZIMZL.js → preload-media-LJXWKTWG.js} +1 -1
- package/dist/quote-T6WYLN7A.js +33 -0
- package/dist/react.js +29 -27
- package/dist/server.js +97 -19
- package/dist/template-catalog.d.ts +154 -19
- package/dist/template-catalog.js +1 -1
- package/dist/test.js +1 -1
- package/docs/customization.md +1 -1
- package/docs/maintainers/cinematic-migration.md +4 -0
- package/docs/media-and-audio.md +3 -3
- package/docs/provider-integration.md +1 -1
- package/package.json +1 -1
- package/registry/items/comparison.json +71 -4
- package/registry/items/editorialTimeline.json +71 -4
- package/registry/items/keyFigure.json +69 -4
- package/registry/items/quote.json +71 -4
- package/starters/video-chat/package.json +1 -1
- package/dist/focus-cards-TJ72BT7U.js +0 -20
- package/dist/key-figure-GYENXKH3.js +0 -20
- package/dist/quote-EW5HQA6H.js +0 -23
- package/registry/items/focusCards.json +0 -90
package/dist/react.js
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
} from "./chunk-7NZOMTAL.js";
|
|
31
31
|
import {
|
|
32
32
|
getBuiltinTemplateMetadata
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-IIN5M5HW.js";
|
|
34
34
|
import "./chunk-3O7OMMMF.js";
|
|
35
35
|
import {
|
|
36
36
|
assertTemplateTransitionMetadata
|
|
@@ -40,8 +40,8 @@ import {
|
|
|
40
40
|
VideoFrame,
|
|
41
41
|
getDimensions,
|
|
42
42
|
sceneReadinessKey
|
|
43
|
-
} from "./chunk-
|
|
44
|
-
import "./chunk-
|
|
43
|
+
} from "./chunk-ELVOT2FQ.js";
|
|
44
|
+
import "./chunk-224QNWRA.js";
|
|
45
45
|
import "./chunk-TVIU23OM.js";
|
|
46
46
|
import {
|
|
47
47
|
getVideoDuration,
|
|
@@ -93,14 +93,13 @@ import { createElement } from "react";
|
|
|
93
93
|
|
|
94
94
|
// src/visual-system/catalog/builtin-loaders.generated.ts
|
|
95
95
|
var GENERATED_BUILTIN_TEMPLATE_LOADERS = {
|
|
96
|
-
"cinemaMedia": () => import("./cinema-media-
|
|
96
|
+
"cinemaMedia": () => import("./cinema-media-C7OUPNSH.js").then((module) => ({ default: module.MediaSceneTemplate })),
|
|
97
97
|
"chapterTitle": () => import("./chapter-title-YRLIQY3V.js").then((module) => ({ default: module.TitleSceneTemplate })),
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"
|
|
103
|
-
"keyFigure": () => import("./key-figure-GYENXKH3.js").then((module) => ({ default: module.KeyFigureSceneTemplate }))
|
|
98
|
+
"editorialTimeline": () => import("./editorial-timeline-EMV5335S.js").then((module) => ({ default: module.TimelineSceneTemplate })),
|
|
99
|
+
"mobileMessage": () => import("./mobile-message-OF7T62B7.js").then((module) => ({ default: module.NotificationSceneTemplate })),
|
|
100
|
+
"comparison": () => import("./comparison-GNZOR7MF.js").then((module) => ({ default: module.ComparisonSceneTemplate })),
|
|
101
|
+
"quote": () => import("./quote-T6WYLN7A.js").then((module) => ({ default: module.QuoteSceneTemplate })),
|
|
102
|
+
"keyFigure": () => import("./key-figure-P37VK425.js").then((module) => ({ default: module.KeyFigureSceneTemplate }))
|
|
104
103
|
};
|
|
105
104
|
|
|
106
105
|
// src/visual-system/catalog/builtin-player.generated.ts
|
|
@@ -121,17 +120,6 @@ var GENERATED_BUILTIN_PLAYER_TEMPLATES = [
|
|
|
121
120
|
},
|
|
122
121
|
"usesGlobalTransition": false
|
|
123
122
|
},
|
|
124
|
-
{
|
|
125
|
-
"id": "focusCards",
|
|
126
|
-
"defaults": {
|
|
127
|
-
"items": [
|
|
128
|
-
"Listen closely",
|
|
129
|
-
"Notice the pattern",
|
|
130
|
-
"Make room for change"
|
|
131
|
-
]
|
|
132
|
-
},
|
|
133
|
-
"usesGlobalTransition": false
|
|
134
|
-
},
|
|
135
123
|
{
|
|
136
124
|
"id": "editorialTimeline",
|
|
137
125
|
"defaults": {
|
|
@@ -145,7 +133,10 @@ var GENERATED_BUILTIN_PLAYER_TEMPLATES = [
|
|
|
145
133
|
{
|
|
146
134
|
"label": "Act"
|
|
147
135
|
}
|
|
148
|
-
]
|
|
136
|
+
],
|
|
137
|
+
"mediaUrl": "",
|
|
138
|
+
"mediaType": "video",
|
|
139
|
+
"mediaPoster": ""
|
|
149
140
|
},
|
|
150
141
|
"usesGlobalTransition": false
|
|
151
142
|
},
|
|
@@ -164,22 +155,33 @@ var GENERATED_BUILTIN_PLAYER_TEMPLATES = [
|
|
|
164
155
|
"id": "comparison",
|
|
165
156
|
"defaults": {
|
|
166
157
|
"leftText": "More distractions",
|
|
167
|
-
"rightText": "More room to think"
|
|
158
|
+
"rightText": "More room to think",
|
|
159
|
+
"mediaUrl": "",
|
|
160
|
+
"mediaType": "video",
|
|
161
|
+
"mediaPoster": ""
|
|
168
162
|
},
|
|
169
163
|
"usesGlobalTransition": false
|
|
170
164
|
},
|
|
171
165
|
{
|
|
172
166
|
"id": "quote",
|
|
173
|
-
"defaults": {
|
|
167
|
+
"defaults": {
|
|
168
|
+
"mediaUrl": "",
|
|
169
|
+
"mediaType": "video",
|
|
170
|
+
"mediaPoster": ""
|
|
171
|
+
},
|
|
174
172
|
"usesGlobalTransition": false
|
|
175
173
|
},
|
|
176
174
|
{
|
|
177
175
|
"id": "keyFigure",
|
|
178
|
-
"defaults": {
|
|
176
|
+
"defaults": {
|
|
177
|
+
"mediaUrl": "",
|
|
178
|
+
"mediaType": "video",
|
|
179
|
+
"mediaPoster": ""
|
|
180
|
+
},
|
|
179
181
|
"usesGlobalTransition": false
|
|
180
182
|
}
|
|
181
183
|
];
|
|
182
|
-
var GENERATED_BUILTIN_VIDEO_BACKDROP_IDS = ["cinemaMedia", "mobileMessage"];
|
|
184
|
+
var GENERATED_BUILTIN_VIDEO_BACKDROP_IDS = ["cinemaMedia", "editorialTimeline", "mobileMessage", "comparison", "quote", "keyFigure"];
|
|
183
185
|
|
|
184
186
|
// src/visual-system/catalog/builtin-player.ts
|
|
185
187
|
function createPreloadableBuiltinTemplate(loader, mediaBackdrop) {
|
|
@@ -235,7 +237,7 @@ function preloadBuiltinTemplate(id) {
|
|
|
235
237
|
|
|
236
238
|
// src/player/warm-scene-media.ts
|
|
237
239
|
function warmSceneMedia(variables) {
|
|
238
|
-
void import("./preload-media-
|
|
240
|
+
void import("./preload-media-LJXWKTWG.js").then((module) => module.preloadSceneMedia(variables)).catch(() => {
|
|
239
241
|
});
|
|
240
242
|
}
|
|
241
243
|
|
package/dist/server.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
BUILTIN_SERVER_TEMPLATE_KIT,
|
|
13
13
|
createServerTemplateRegistry,
|
|
14
14
|
overlayServerTemplateRegistry
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-IR44XKBI.js";
|
|
16
16
|
import {
|
|
17
17
|
createTemplateSceneValidator,
|
|
18
18
|
validateTemplateSceneStructure
|
|
@@ -47,14 +47,77 @@ import {
|
|
|
47
47
|
import {
|
|
48
48
|
createTemplateSystemPrompt,
|
|
49
49
|
getStandardMediaResolverContract
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-2HFO22K2.js";
|
|
51
51
|
import "./chunk-PAJ44TFW.js";
|
|
52
52
|
import "./chunk-EGVQODKU.js";
|
|
53
|
-
import "./chunk-
|
|
53
|
+
import "./chunk-IIN5M5HW.js";
|
|
54
54
|
import "./chunk-3O7OMMMF.js";
|
|
55
55
|
import "./chunk-2E6T633S.js";
|
|
56
56
|
import "./chunk-73NTSFFI.js";
|
|
57
57
|
|
|
58
|
+
// src/server/opening-continuity.ts
|
|
59
|
+
function continueAfterOpening(narration, earlier) {
|
|
60
|
+
const words = (value) => Array.from(value.matchAll(/[\p{L}\p{N}]+(?:['’][\p{L}\p{N}]+)*/gu));
|
|
61
|
+
let remaining = narration;
|
|
62
|
+
for (const previous of [...earlier].reverse()) {
|
|
63
|
+
const known = words(previous), current = words(remaining);
|
|
64
|
+
if (known.length < 5 || known.length > current.length) continue;
|
|
65
|
+
if (!known.every((word, index) => word[0].toLowerCase() === current[index][0].toLowerCase())) continue;
|
|
66
|
+
if (known.length === current.length) return "";
|
|
67
|
+
const last = current[known.length - 1];
|
|
68
|
+
const suffix = remaining.slice(last.index + last[0].length);
|
|
69
|
+
const boundary = suffix.match(/^[”"'’\])]*[.!?…]+[\s”"'’\])]*/u);
|
|
70
|
+
if (boundary) remaining = suffix.slice(boundary[0].length).trim();
|
|
71
|
+
}
|
|
72
|
+
return remaining;
|
|
73
|
+
}
|
|
74
|
+
function createOpeningContinuation(initialOpening) {
|
|
75
|
+
const earlier = initialOpening ? [initialOpening] : [];
|
|
76
|
+
let bodyStarted = false;
|
|
77
|
+
const copy = (authored, narration) => {
|
|
78
|
+
if (continueAfterOpening(authored, earlier) !== "") return authored;
|
|
79
|
+
const next = continueAfterOpening(narration, earlier).trim();
|
|
80
|
+
return next && [...next].length <= 65 && /[.!?…][”"’')\]]*$/u.test(next) ? next : authored;
|
|
81
|
+
};
|
|
82
|
+
return {
|
|
83
|
+
copy,
|
|
84
|
+
remember(line) {
|
|
85
|
+
if (line.trim()) earlier.push(line);
|
|
86
|
+
},
|
|
87
|
+
narration(line) {
|
|
88
|
+
return continueAfterOpening(line, earlier);
|
|
89
|
+
},
|
|
90
|
+
line(rawLine) {
|
|
91
|
+
if (bodyStarted || earlier.length === 0) return rawLine;
|
|
92
|
+
let part;
|
|
93
|
+
try {
|
|
94
|
+
part = JSON.parse(rawLine);
|
|
95
|
+
} catch {
|
|
96
|
+
return rawLine;
|
|
97
|
+
}
|
|
98
|
+
if (!part || part.type !== "scene.add" || part.placement === "closer") return rawLine;
|
|
99
|
+
const scene = part.scene;
|
|
100
|
+
if (!scene) return rawLine;
|
|
101
|
+
if (typeof scene.narration !== "string") {
|
|
102
|
+
bodyStarted = true;
|
|
103
|
+
return rawLine;
|
|
104
|
+
}
|
|
105
|
+
const narration = continueAfterOpening(scene.narration, earlier);
|
|
106
|
+
if (!narration && scene.templateId === "cinemaMedia") return null;
|
|
107
|
+
const variables = scene.variables;
|
|
108
|
+
if (!narration && scene.templateId === "chapterTitle" && typeof variables?.title === "string" && !continueAfterOpening(variables.title, earlier)) return null;
|
|
109
|
+
bodyStarted = true;
|
|
110
|
+
if (!narration) return rawLine;
|
|
111
|
+
const field = scene.templateId === "cinemaMedia" ? "fallbackText" : scene.templateId === "chapterTitle" ? "title" : void 0;
|
|
112
|
+
const authored = field && variables?.[field];
|
|
113
|
+
const updated = typeof authored === "string" ? copy(authored, narration) : void 0;
|
|
114
|
+
const copyChanged = typeof authored === "string" && updated !== authored;
|
|
115
|
+
if (narration === scene.narration && !copyChanged) return rawLine;
|
|
116
|
+
return JSON.stringify({ ...part, scene: { ...scene, narration, ...copyChanged ? { variables: { ...variables, [field]: updated } } : {} } });
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
58
121
|
// src/server/request-validation.ts
|
|
59
122
|
var MAX_GENERATED_LOOK_LENGTH = 1e3;
|
|
60
123
|
function boundedString(value, path) {
|
|
@@ -865,11 +928,12 @@ function createVideoHandler(options) {
|
|
|
865
928
|
function createVideoChatResponseInstructions(generatedVideoAvailable, openingAlreadyProvided = false, maxGeneratedVideos = 5) {
|
|
866
929
|
return [
|
|
867
930
|
"Respond as a coherent short film: establish, develop, then land a useful or emotional payoff. Match the user's requested form.",
|
|
868
|
-
generatedVideoAvailable ? 'First emit one host-consumed opening JSON object: {"type":"video-chat.opening","spokenHook":"6-9 words","mediaKeyword":"literal subject","firstShot":{"text":"short grounded fallback","narration":"one natural
|
|
931
|
+
generatedVideoAvailable ? 'First emit one host-consumed opening JSON object: {"type":"video-chat.opening","spokenHook":"6-9 words","mediaKeyword":"literal subject","firstShot":{"text":"short grounded fallback","narration":"one natural sentence advancing the hook","mediaKeyword":"2-8 concrete words","shotDirection":"optional framing and action"}}. Include firstShot only when a distinctive illustrative shot serves the story; omit it for an abstract explanation best opened with graphics. When present, the host inserts it once and begins generation immediately; do not emit it again.' : openingAlreadyProvided ? "Start directly with scene.add; the opening has already been supplied." : 'First emit {"type":"video-chat.opening","spokenHook":"6-9 words","mediaKeyword":"literal subject"}. This is host-consumed, not a scene.',
|
|
869
932
|
openingAlreadyProvided ? "Preserve the supplied opening exactly; continue it without repeating its words or claim." : void 0,
|
|
933
|
+
"The spokenHook is already heard before the first scene. Start firstShot.narration with the next fact, cause, action or consequence; never restate the hook. The first ordinary scene must then advance beyond firstShot rather than repeat its narration or opening claim. If firstShot is omitted, that first scene must advance the hook directly. firstShot.text, fallbackText and chapter titles must also express that new beat, not reuse the hook or prior shot copy; write a short complete grounded thought within the schema budget, never a clipped statistic or qualifying clause.",
|
|
870
934
|
"Continue with only as many scenes as the story and duration need. Never pad to a fixed count. Every emitted scene carries narration beside variables and timing; no additional narration request should be needed.",
|
|
871
|
-
"
|
|
872
|
-
"Use the installed catalog:
|
|
935
|
+
"Make most of the film relevant footage: use full-bleed media for action, subjects and atmosphere, with graphics only to clarify a specific relationship or piece of evidence. Maintain consistent setting, lighting and subject while varying shot scale. Avoid unrelated cinematic montages.",
|
|
936
|
+
"Use the installed catalog: ordered events, comparison, exact quote, one key figure, chapter or a message only when its narrative job fits. At most one graphic-led explanatory beat per 30 seconds, plus a brief chapter opening when needed. Do not place graphic beats consecutively unless no honest relevant media is available. Give media-capable graphics a relevant background when it supports the meaning; keep black when no matching media exists. Do not force every template into a video or use lists of bullets.",
|
|
873
937
|
`At most ${generatedVideoAvailable ? maxGeneratedVideos : 0} generated-video attempts are available. Media scenes choose mediaSource=generate for distinctive illustrative shots or mediaSource=stock for generic verified imagery. A stock miss is not permission to broaden essential details. Do not spend generation on every scene.`,
|
|
874
938
|
"Each mediaKeyword is a literal filmable subject/action, 2\u20138 words, maximum 80 characters. Use optional shotDirection for action, camera framing and continuity; it does not change the literal stock subject. Supply a short grounded fallbackText when the schema declares it. Do not put visible headline text over full-bleed footage.",
|
|
875
939
|
"No invented quotations, attribution, statistics, personal evidence or URLs. Creative stories may be invented when requested; do not present generated illustration as historical evidence.",
|
|
@@ -1111,6 +1175,19 @@ function interceptOpeningPlan(source, options) {
|
|
|
1111
1175
|
const textStream = (async function* () {
|
|
1112
1176
|
let buffer = "";
|
|
1113
1177
|
let decided = !options.expectOpening;
|
|
1178
|
+
const continuation = createOpeningContinuation(options.openingLine);
|
|
1179
|
+
const acceptOpening = (opening) => {
|
|
1180
|
+
if (!options.openingProvided) {
|
|
1181
|
+
options.publish(opening.line ? opening : void 0);
|
|
1182
|
+
continuation.remember(opening.line);
|
|
1183
|
+
}
|
|
1184
|
+
if (!options.generatedVideoAvailable || !opening.firstShot) return void 0;
|
|
1185
|
+
const narration = continuation.narration(opening.firstShot.narration);
|
|
1186
|
+
if (!narration) return void 0;
|
|
1187
|
+
const text = continuation.copy(opening.firstShot.text, narration);
|
|
1188
|
+
continuation.remember(narration);
|
|
1189
|
+
return JSON.stringify(reservedFirstScene(options.requestId, { ...opening.firstShot, text, narration }));
|
|
1190
|
+
};
|
|
1114
1191
|
try {
|
|
1115
1192
|
for await (const delta of upstream) {
|
|
1116
1193
|
if (typeof delta !== "string") throw new Error("The LLM adapter returned a non-text delta");
|
|
@@ -1124,17 +1201,16 @@ function interceptOpeningPlan(source, options) {
|
|
|
1124
1201
|
const opening = readOpeningPlanLine(line);
|
|
1125
1202
|
decided = true;
|
|
1126
1203
|
if (opening) {
|
|
1127
|
-
|
|
1128
|
-
if (
|
|
1129
|
-
yield `${JSON.stringify(reservedFirstScene(options.requestId, opening.firstShot))}
|
|
1204
|
+
const firstScene = acceptOpening(opening);
|
|
1205
|
+
if (firstScene) yield `${firstScene}
|
|
1130
1206
|
`;
|
|
1131
|
-
}
|
|
1132
1207
|
newline = buffer.indexOf("\n");
|
|
1133
1208
|
continue;
|
|
1134
1209
|
}
|
|
1135
1210
|
options.publish(void 0);
|
|
1136
1211
|
}
|
|
1137
|
-
|
|
1212
|
+
const continued = continuation.line(rawLine);
|
|
1213
|
+
if (continued != null) yield `${continued}
|
|
1138
1214
|
`;
|
|
1139
1215
|
newline = buffer.indexOf("\n");
|
|
1140
1216
|
}
|
|
@@ -1145,17 +1221,17 @@ function interceptOpeningPlan(source, options) {
|
|
|
1145
1221
|
const opening = readOpeningPlanLine(line);
|
|
1146
1222
|
decided = true;
|
|
1147
1223
|
if (opening) {
|
|
1148
|
-
|
|
1149
|
-
if (
|
|
1150
|
-
yield `${JSON.stringify(reservedFirstScene(options.requestId, opening.firstShot))}
|
|
1224
|
+
const firstScene = acceptOpening(opening);
|
|
1225
|
+
if (firstScene) yield `${firstScene}
|
|
1151
1226
|
`;
|
|
1152
|
-
}
|
|
1153
1227
|
} else {
|
|
1154
1228
|
options.publish(void 0);
|
|
1155
|
-
|
|
1229
|
+
const continued = continuation.line(buffer);
|
|
1230
|
+
if (continued != null) yield continued;
|
|
1156
1231
|
}
|
|
1157
1232
|
} else {
|
|
1158
|
-
|
|
1233
|
+
const continued = continuation.line(buffer);
|
|
1234
|
+
if (continued != null) yield continued;
|
|
1159
1235
|
}
|
|
1160
1236
|
}
|
|
1161
1237
|
} finally {
|
|
@@ -1332,7 +1408,7 @@ function createVideoChatHandler(options) {
|
|
|
1332
1408
|
const heroQuery = welcomeOptions?.heroQuery;
|
|
1333
1409
|
let welcomeResponse;
|
|
1334
1410
|
let requestSequence = 0;
|
|
1335
|
-
const responseHandler = (requestId, openingProvided, openingChannel) => {
|
|
1411
|
+
const responseHandler = (requestId, openingProvided, openingChannel, openingLine) => {
|
|
1336
1412
|
const generatedVideoAvailable = generateVideo != null && maxGeneratedVideos > 0;
|
|
1337
1413
|
let lifecycle;
|
|
1338
1414
|
let generatedAttempts = 0;
|
|
@@ -1400,6 +1476,7 @@ function createVideoChatHandler(options) {
|
|
|
1400
1476
|
return interceptOpeningPlan(videoOptions.streamText(context), {
|
|
1401
1477
|
expectOpening: generatedVideoAvailable || !openingProvided,
|
|
1402
1478
|
openingProvided,
|
|
1479
|
+
openingLine,
|
|
1403
1480
|
requestId,
|
|
1404
1481
|
generatedVideoAvailable,
|
|
1405
1482
|
publish: openingChannel.publish
|
|
@@ -1569,7 +1646,8 @@ function createVideoChatHandler(options) {
|
|
|
1569
1646
|
const response = await responseHandler(
|
|
1570
1647
|
requestId,
|
|
1571
1648
|
input.opening != null,
|
|
1572
|
-
openingChannel
|
|
1649
|
+
openingChannel,
|
|
1650
|
+
input.opening
|
|
1573
1651
|
)(videoRequest);
|
|
1574
1652
|
return streamVideoChatOpening(response, openingChannel.ready);
|
|
1575
1653
|
}
|
|
@@ -66,25 +66,6 @@ declare const BUILTIN_TEMPLATE_SCHEMAS: {
|
|
|
66
66
|
readonly required: readonly ["title"];
|
|
67
67
|
readonly additionalProperties: false;
|
|
68
68
|
};
|
|
69
|
-
readonly focusCards: {
|
|
70
|
-
readonly type: "object";
|
|
71
|
-
readonly properties: {
|
|
72
|
-
readonly items: {
|
|
73
|
-
readonly type: "array";
|
|
74
|
-
readonly minItems: 2;
|
|
75
|
-
readonly maxItems: 4;
|
|
76
|
-
readonly items: {
|
|
77
|
-
readonly type: "string";
|
|
78
|
-
readonly minLength: 1;
|
|
79
|
-
readonly maxLength: 55;
|
|
80
|
-
};
|
|
81
|
-
readonly default: readonly ["Listen closely", "Notice the pattern", "Make room for change"];
|
|
82
|
-
readonly description: "2–4 parallel phrases, about 2–6 words each; no heading or numbering.";
|
|
83
|
-
};
|
|
84
|
-
};
|
|
85
|
-
readonly required: readonly ["items"];
|
|
86
|
-
readonly additionalProperties: false;
|
|
87
|
-
};
|
|
88
69
|
readonly editorialTimeline: {
|
|
89
70
|
readonly type: "object";
|
|
90
71
|
readonly properties: {
|
|
@@ -113,9 +94,48 @@ declare const BUILTIN_TEMPLATE_SCHEMAS: {
|
|
|
113
94
|
}];
|
|
114
95
|
readonly description: "3–5 ordered events or actions, each with one short label; no dates.";
|
|
115
96
|
};
|
|
97
|
+
readonly mediaKeyword: {
|
|
98
|
+
readonly type: "string";
|
|
99
|
+
readonly format: "stock-media-keyword";
|
|
100
|
+
readonly minLength: 1;
|
|
101
|
+
readonly maxLength: 80;
|
|
102
|
+
readonly description: "2–8 word literal subject/action search intent, maximum 80 characters. Host resolves URLs.";
|
|
103
|
+
readonly examples: readonly ["Ocean waves breaking on a rocky shore"];
|
|
104
|
+
};
|
|
105
|
+
readonly mediaUrl: {
|
|
106
|
+
readonly type: "string";
|
|
107
|
+
readonly format: "uri";
|
|
108
|
+
readonly description: "Host-only approved photo or video URL.";
|
|
109
|
+
readonly default: "";
|
|
110
|
+
};
|
|
111
|
+
readonly mediaType: {
|
|
112
|
+
readonly type: "string";
|
|
113
|
+
readonly enum: readonly ["photo", "video"];
|
|
114
|
+
readonly default: "video";
|
|
115
|
+
readonly description: "Host-resolved asset kind.";
|
|
116
|
+
};
|
|
117
|
+
readonly mediaPoster: {
|
|
118
|
+
readonly type: "string";
|
|
119
|
+
readonly format: "uri";
|
|
120
|
+
readonly description: "Host-only approved poster URL for video decoding.";
|
|
121
|
+
readonly default: "";
|
|
122
|
+
};
|
|
123
|
+
readonly shotDirection: {
|
|
124
|
+
readonly type: "string";
|
|
125
|
+
readonly maxLength: 220;
|
|
126
|
+
readonly description: "Optional action, framing and continuity for generation. Preserve the subject; do not request rendered text.";
|
|
127
|
+
};
|
|
128
|
+
readonly mediaSource: {
|
|
129
|
+
readonly type: "string";
|
|
130
|
+
readonly enum: readonly ["generate", "stock"];
|
|
131
|
+
readonly description: "Generate distinctive illustrative shots; use approved stock for familiar observable subjects.";
|
|
132
|
+
};
|
|
116
133
|
};
|
|
117
134
|
readonly required: readonly ["events"];
|
|
118
135
|
readonly additionalProperties: false;
|
|
136
|
+
readonly "x-vanillasky": {
|
|
137
|
+
readonly allowsStockMedia: true;
|
|
138
|
+
};
|
|
119
139
|
};
|
|
120
140
|
readonly mobileMessage: {
|
|
121
141
|
readonly type: "object";
|
|
@@ -202,9 +222,48 @@ declare const BUILTIN_TEMPLATE_SCHEMAS: {
|
|
|
202
222
|
readonly default: "More room to think";
|
|
203
223
|
readonly description: "Second real alternative, parallel to the first.";
|
|
204
224
|
};
|
|
225
|
+
readonly mediaKeyword: {
|
|
226
|
+
readonly type: "string";
|
|
227
|
+
readonly format: "stock-media-keyword";
|
|
228
|
+
readonly minLength: 1;
|
|
229
|
+
readonly maxLength: 80;
|
|
230
|
+
readonly description: "2–8 word literal subject/action search intent, maximum 80 characters. Host resolves URLs.";
|
|
231
|
+
readonly examples: readonly ["Ocean waves breaking on a rocky shore"];
|
|
232
|
+
};
|
|
233
|
+
readonly mediaUrl: {
|
|
234
|
+
readonly type: "string";
|
|
235
|
+
readonly format: "uri";
|
|
236
|
+
readonly description: "Host-only approved photo or video URL.";
|
|
237
|
+
readonly default: "";
|
|
238
|
+
};
|
|
239
|
+
readonly mediaType: {
|
|
240
|
+
readonly type: "string";
|
|
241
|
+
readonly enum: readonly ["photo", "video"];
|
|
242
|
+
readonly default: "video";
|
|
243
|
+
readonly description: "Host-resolved asset kind.";
|
|
244
|
+
};
|
|
245
|
+
readonly mediaPoster: {
|
|
246
|
+
readonly type: "string";
|
|
247
|
+
readonly format: "uri";
|
|
248
|
+
readonly description: "Host-only approved poster URL for video decoding.";
|
|
249
|
+
readonly default: "";
|
|
250
|
+
};
|
|
251
|
+
readonly shotDirection: {
|
|
252
|
+
readonly type: "string";
|
|
253
|
+
readonly maxLength: 220;
|
|
254
|
+
readonly description: "Optional action, framing and continuity for generation. Preserve the subject; do not request rendered text.";
|
|
255
|
+
};
|
|
256
|
+
readonly mediaSource: {
|
|
257
|
+
readonly type: "string";
|
|
258
|
+
readonly enum: readonly ["generate", "stock"];
|
|
259
|
+
readonly description: "Generate distinctive illustrative shots; use approved stock for familiar observable subjects.";
|
|
260
|
+
};
|
|
205
261
|
};
|
|
206
262
|
readonly required: readonly ["leftText", "rightText"];
|
|
207
263
|
readonly additionalProperties: false;
|
|
264
|
+
readonly "x-vanillasky": {
|
|
265
|
+
readonly allowsStockMedia: true;
|
|
266
|
+
};
|
|
208
267
|
};
|
|
209
268
|
readonly quote: {
|
|
210
269
|
readonly type: "object";
|
|
@@ -224,9 +283,48 @@ declare const BUILTIN_TEMPLATE_SCHEMAS: {
|
|
|
224
283
|
readonly examples: readonly ["Illustrative example"];
|
|
225
284
|
readonly description: "Grounded attribution belonging to these exact quoted words.";
|
|
226
285
|
};
|
|
286
|
+
readonly mediaKeyword: {
|
|
287
|
+
readonly type: "string";
|
|
288
|
+
readonly format: "stock-media-keyword";
|
|
289
|
+
readonly minLength: 1;
|
|
290
|
+
readonly maxLength: 80;
|
|
291
|
+
readonly description: "2–8 word literal subject/action search intent, maximum 80 characters. Host resolves URLs.";
|
|
292
|
+
readonly examples: readonly ["Ocean waves breaking on a rocky shore"];
|
|
293
|
+
};
|
|
294
|
+
readonly mediaUrl: {
|
|
295
|
+
readonly type: "string";
|
|
296
|
+
readonly format: "uri";
|
|
297
|
+
readonly description: "Host-only approved photo or video URL.";
|
|
298
|
+
readonly default: "";
|
|
299
|
+
};
|
|
300
|
+
readonly mediaType: {
|
|
301
|
+
readonly type: "string";
|
|
302
|
+
readonly enum: readonly ["photo", "video"];
|
|
303
|
+
readonly default: "video";
|
|
304
|
+
readonly description: "Host-resolved asset kind.";
|
|
305
|
+
};
|
|
306
|
+
readonly mediaPoster: {
|
|
307
|
+
readonly type: "string";
|
|
308
|
+
readonly format: "uri";
|
|
309
|
+
readonly description: "Host-only approved poster URL for video decoding.";
|
|
310
|
+
readonly default: "";
|
|
311
|
+
};
|
|
312
|
+
readonly shotDirection: {
|
|
313
|
+
readonly type: "string";
|
|
314
|
+
readonly maxLength: 220;
|
|
315
|
+
readonly description: "Optional action, framing and continuity for generation. Preserve the subject; do not request rendered text.";
|
|
316
|
+
};
|
|
317
|
+
readonly mediaSource: {
|
|
318
|
+
readonly type: "string";
|
|
319
|
+
readonly enum: readonly ["generate", "stock"];
|
|
320
|
+
readonly description: "Generate distinctive illustrative shots; use approved stock for familiar observable subjects.";
|
|
321
|
+
};
|
|
227
322
|
};
|
|
228
323
|
readonly required: readonly ["quote", "attribution"];
|
|
229
324
|
readonly additionalProperties: false;
|
|
325
|
+
readonly "x-vanillasky": {
|
|
326
|
+
readonly allowsStockMedia: true;
|
|
327
|
+
};
|
|
230
328
|
};
|
|
231
329
|
readonly keyFigure: {
|
|
232
330
|
readonly type: "object";
|
|
@@ -246,11 +344,48 @@ declare const BUILTIN_TEMPLATE_SCHEMAS: {
|
|
|
246
344
|
readonly examples: readonly ["Illustrative example"];
|
|
247
345
|
readonly description: "Exactly one short label identifying the quantity and its context.";
|
|
248
346
|
};
|
|
347
|
+
readonly mediaKeyword: {
|
|
348
|
+
readonly type: "string";
|
|
349
|
+
readonly format: "stock-media-keyword";
|
|
350
|
+
readonly minLength: 1;
|
|
351
|
+
readonly maxLength: 80;
|
|
352
|
+
readonly description: "2–8 word literal subject/action search intent, maximum 80 characters. Host resolves URLs.";
|
|
353
|
+
readonly examples: readonly ["Ocean waves breaking on a rocky shore"];
|
|
354
|
+
};
|
|
355
|
+
readonly mediaUrl: {
|
|
356
|
+
readonly type: "string";
|
|
357
|
+
readonly format: "uri";
|
|
358
|
+
readonly description: "Host-only approved photo or video URL.";
|
|
359
|
+
readonly default: "";
|
|
360
|
+
};
|
|
361
|
+
readonly mediaType: {
|
|
362
|
+
readonly type: "string";
|
|
363
|
+
readonly enum: readonly ["photo", "video"];
|
|
364
|
+
readonly default: "video";
|
|
365
|
+
readonly description: "Host-resolved asset kind.";
|
|
366
|
+
};
|
|
367
|
+
readonly mediaPoster: {
|
|
368
|
+
readonly type: "string";
|
|
369
|
+
readonly format: "uri";
|
|
370
|
+
readonly description: "Host-only approved poster URL for video decoding.";
|
|
371
|
+
readonly default: "";
|
|
372
|
+
};
|
|
373
|
+
readonly shotDirection: {
|
|
374
|
+
readonly type: "string";
|
|
375
|
+
readonly maxLength: 220;
|
|
376
|
+
readonly description: "Optional action, framing and continuity for generation. Preserve the subject; do not request rendered text.";
|
|
377
|
+
};
|
|
378
|
+
readonly mediaSource: {
|
|
379
|
+
readonly type: "string";
|
|
380
|
+
readonly enum: readonly ["generate", "stock"];
|
|
381
|
+
readonly description: "Generate distinctive illustrative shots; use approved stock for familiar observable subjects.";
|
|
382
|
+
};
|
|
249
383
|
};
|
|
250
384
|
readonly required: readonly ["value", "label"];
|
|
251
385
|
readonly additionalProperties: false;
|
|
252
386
|
readonly "x-vanillasky": {
|
|
253
387
|
readonly requiresStat: true;
|
|
388
|
+
readonly allowsStockMedia: true;
|
|
254
389
|
};
|
|
255
390
|
};
|
|
256
391
|
};
|
package/dist/template-catalog.js
CHANGED
package/dist/test.js
CHANGED
|
@@ -235,7 +235,7 @@ async function* simulateVideoStream(parts, options = {}) {
|
|
|
235
235
|
}
|
|
236
236
|
const { createVideo } = await import("./compose-video-TBFTONUC.js");
|
|
237
237
|
const { createTextDeltaVideoPlanner } = await import("./text-stream-LD364KBI.js");
|
|
238
|
-
const { BUILTIN_SERVER_TEMPLATE_KIT } = await import("./builtin-server-
|
|
238
|
+
const { BUILTIN_SERVER_TEMPLATE_KIT } = await import("./builtin-server-W4PLJUZ5.js");
|
|
239
239
|
const { createTemplateSceneValidator } = await import("./validate-4OUD2CLX.js");
|
|
240
240
|
const controller = new AbortController();
|
|
241
241
|
const forwardAbort = () => controller.abort(options.signal?.reason);
|
package/docs/customization.md
CHANGED
|
@@ -52,7 +52,7 @@ explain with their own composition and motion. There is no brand-kit option.
|
|
|
52
52
|
The host can provide a shared `generatedLook` description for media preparation.
|
|
53
53
|
Custom source-owned templates can define their own visual language in code.
|
|
54
54
|
Do not rely on old global brand, text-effect, or gradient controls to restyle
|
|
55
|
-
the
|
|
55
|
+
the seven cinematic templates.
|
|
56
56
|
|
|
57
57
|
## Opening
|
|
58
58
|
|
|
@@ -32,3 +32,7 @@ Evidence: persistence tests preserve the untouched old release fixture and asser
|
|
|
32
32
|
The cinematic templates use `-apple-system, BlinkMacSystemFont, "Helvetica Neue", Roboto, Arial, sans-serif` at regular and medium weights. Apple devices keep native system typography. The existing `@vanillaskyai/video/video-chat.css` entry registers packaged Roboto v51 WOFF2 subsets as the fallback for environments without those fonts. Standalone player and source-owned template integrations should also import that stylesheet. No font is fetched from Google at runtime; browsers fetch local packaged subsets only when Roboto is selected for the rendered glyphs. The font assets include the SIL Open Font License and a source/hash manifest.
|
|
33
33
|
|
|
34
34
|
Live native fonts and a Linux renderer’s Roboto have slightly different metrics. For repeatable exports, keep the browser, installed fonts, viewport and package version fixed, and await `document.fonts.ready` after mounting the final scene before capturing frames. This is a host export responsibility; the SDK does not add a separate export API or force downloaded fonts onto Apple devices.
|
|
35
|
+
|
|
36
|
+
## Media-led follow-up
|
|
37
|
+
|
|
38
|
+
The owner requested removing `focusCards`. Regenerate persisted videos using that ID; migrate parallel explanations to narration over footage rather than another bullet layout. The remaining seven templates retain their IDs. Comparison, quote, key figure and timeline accept optional standard media variables and remain readable on black when assets are absent. No provider callback signatures or host limits change.
|
package/docs/media-and-audio.md
CHANGED
|
@@ -8,14 +8,14 @@ all credentials out of React and the browser bundle.
|
|
|
8
8
|
|
|
9
9
|
## One cinematic mode
|
|
10
10
|
|
|
11
|
-
The director combines relevant footage and
|
|
11
|
+
The director combines relevant footage and seven editorial templates. Graphics
|
|
12
12
|
use black and white; footage carries atmosphere and concrete action. Each media
|
|
13
13
|
scene declares `mediaSource: "stock"` or `"generate"`. Provider availability and
|
|
14
14
|
host budgets constrain those choices. There is no all-stock or all-AI switch.
|
|
15
15
|
|
|
16
|
-
The canonical templates are `cinemaMedia`, `chapterTitle`,
|
|
16
|
+
The canonical templates are `cinemaMedia`, `chapterTitle`,
|
|
17
17
|
`editorialTimeline`, `mobileMessage`, `comparison`, `quote`, and `keyFigure`.
|
|
18
|
-
|
|
18
|
+
All except `chapterTitle` accept optional media backgrounds. Editorial overlays use soft text shadows and a dark contrast scrim over relevant media, and fall back to black. Use at most one explanatory overlay per typical thirty-second answer. Full-bleed
|
|
19
19
|
footage has no headline; narration and subtitles carry the explanation.
|
|
20
20
|
|
|
21
21
|
## Reviewed stock
|
|
@@ -180,7 +180,7 @@ is intentionally substantial. It is stable for the same SDK version, template
|
|
|
180
180
|
kit, media policy, and base prompt. Record input-token usage, keep the selected
|
|
181
181
|
kit no broader than the product needs, and enable provider-side prompt caching
|
|
182
182
|
where the chosen provider/model supports it. VanillaSky does not assume one
|
|
183
|
-
provider's cache controls in its provider-neutral adapter. The cinematic catalog contains
|
|
183
|
+
provider's cache controls in its provider-neutral adapter. The cinematic catalog contains seven templates; use provider-reported token
|
|
184
184
|
usage as the authoritative measurement rather than a character estimate.
|
|
185
185
|
|
|
186
186
|
Provider finish reasons `error` and `tool-calls` are terminal failures.
|