@vanillaskyai/video 0.8.8 → 0.9.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 +30 -0
- package/PUBLIC-API.md +5 -8
- package/dist/{builtin-server-CUYPIDE7.js → builtin-server-HW6HGXCZ.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 +6 -15
- package/dist/{chunk-2USVB3CY.js → chunk-3ZTEFJIR.js} +285 -178
- package/dist/chunk-4YM2M62S.js +13 -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-EWWCQFTI.js +18 -0
- package/dist/{chunk-MXZSDGZQ.js → chunk-G7IZBBWF.js} +14 -9
- package/dist/{chunk-KT3M7KDL.js → chunk-HKUI5BTB.js} +3 -3
- package/dist/{chunk-LMG3GHLL.js → chunk-IQMYK5DX.js} +29 -3
- package/dist/chunk-LH4BPALA.js +564 -0
- package/dist/{chunk-OWBT45EN.js → chunk-MQILEEXC.js} +1 -1
- package/dist/chunk-MXEYPK7M.js +552 -0
- package/dist/{chunk-AITKH6QT.js → chunk-OR52UMSF.js} +13 -39
- 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-224QNWRA.js → chunk-UDIODEDK.js} +1 -5
- package/dist/{chunk-3VRMKFM7.js → chunk-ZDJNFA52.js} +11 -24
- package/dist/cinema-media-YQHSIFDA.js +11 -0
- package/dist/cli.js +18 -9
- package/dist/comparison-RZMMHZR2.js +27 -0
- package/dist/compose-video-TBFTONUC.js +12 -0
- package/dist/editorial-timeline-OZX7OS6G.js +36 -0
- package/dist/{events-BQ6z264n.d.ts → events-B4YCc4vc.d.ts} +1 -1
- package/dist/focus-cards-TJ72BT7U.js +20 -0
- package/dist/index.d.ts +4 -6
- package/dist/index.js +3 -7
- package/dist/key-figure-GYENXKH3.js +20 -0
- package/dist/{kit-tQnCPMOM.d.ts → kit-DrRpdn0p.d.ts} +2 -2
- package/dist/mobile-message-UZUPIKHD.js +49 -0
- package/dist/{preload-media-LJXWKTWG.js → preload-media-CFTZIMZL.js} +1 -1
- package/dist/quote-EW5HQA6H.js +23 -0
- package/dist/react.d.ts +21 -11
- package/dist/react.js +590 -833
- package/dist/scene-video-backdrop-PCTARAAJ.js +7 -0
- package/dist/server.d.ts +7 -8
- package/dist/server.js +91 -74
- package/dist/{system-prompt-RRXIWDDD.js → system-prompt-SYRT5DWM.js} +1 -1
- package/dist/template-catalog.d.ts +257 -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 +34 -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 +101 -0
- package/registry/items/editorialTimeline.json +105 -0
- package/registry/items/focusCards.json +90 -0
- package/registry/items/keyFigure.json +97 -0
- package/registry/items/mobileMessage.json +153 -0
- package/registry/items/quote.json +94 -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/dist/server.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as VideoFinishReason, V as VideoWarning, b as VideoEvent } from './events-
|
|
3
|
-
export { c as VideoWarningCategory } from './events-
|
|
4
|
-
import { S as SceneTemplateMetadata } from './catalog-types-
|
|
5
|
-
import { f as VideoChatWelcomeOptions } from './types-
|
|
6
|
-
export { d as VideoChatCapabilities, g as VideoChatConversationTurn, V as VideoChatMode, h as VideoChatWelcomePrompt } from './types-
|
|
1
|
+
import { k as VideoGenerationContext, l as VideoPlanner, m as VideoRequest, a as VideoCapabilities, j as VideoInput, d as VideoAudio, n as VideoSceneValidator, g as VideoTemplatePacing, o as VideoSnapshotRetention, p as VideoResumeCursor, q as VideoSceneValidationContext, e as VideoScene, b as VideoOrientation } from './types-DdZw4GRQ.js';
|
|
2
|
+
import { a as VideoFinishReason, V as VideoWarning, b as VideoEvent } from './events-B4YCc4vc.js';
|
|
3
|
+
export { c as VideoWarningCategory } from './events-B4YCc4vc.js';
|
|
4
|
+
import { S as SceneTemplateMetadata } from './catalog-types-WTbLP6Jh.js';
|
|
5
|
+
import { f as VideoChatWelcomeOptions } from './types-CdBmNTGD.js';
|
|
6
|
+
export { d as VideoChatCapabilities, g as VideoChatConversationTurn, V as VideoChatMode, h as VideoChatWelcomePrompt } from './types-CdBmNTGD.js';
|
|
7
7
|
|
|
8
8
|
interface VideoProviderUsage {
|
|
9
9
|
inputTokens?: number;
|
|
@@ -170,8 +170,7 @@ interface VideoHandlerOptions extends Omit<VideoStreamHandlerOptions, "generate"
|
|
|
170
170
|
*
|
|
171
171
|
* Unbounded by default, which is right when media is searched for and wrong
|
|
172
172
|
* when it is generated: the planner decides the scene count, and every scene
|
|
173
|
-
* is then a paid clip. Past the ceiling a scene
|
|
174
|
-
* gradient, and a `media_budget_reached` warning says it happened.
|
|
173
|
+
* is then a paid clip. Past the ceiling a scene uses its grounded text fallback, and a `media_budget_reached` warning says it happened.
|
|
175
174
|
*/
|
|
176
175
|
maxResolvedMedia?: number;
|
|
177
176
|
/**
|
package/dist/server.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createTextDeltaVideoPlanner
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PDQFQIQW.js";
|
|
4
4
|
import {
|
|
5
5
|
createVideo,
|
|
6
6
|
invokeIsolated
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ZDJNFA52.js";
|
|
8
8
|
import {
|
|
9
9
|
getGenerationLifecycleSink
|
|
10
10
|
} from "./chunk-E7CL7UPB.js";
|
|
@@ -12,10 +12,11 @@ import {
|
|
|
12
12
|
BUILTIN_SERVER_TEMPLATE_KIT,
|
|
13
13
|
createServerTemplateRegistry,
|
|
14
14
|
overlayServerTemplateRegistry
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-MQILEEXC.js";
|
|
16
16
|
import {
|
|
17
|
-
createTemplateSceneValidator
|
|
18
|
-
|
|
17
|
+
createTemplateSceneValidator,
|
|
18
|
+
validateTemplateSceneStructure
|
|
19
|
+
} from "./chunk-IQMYK5DX.js";
|
|
19
20
|
import {
|
|
20
21
|
MEDIA_RECOVERY_NOTICE,
|
|
21
22
|
decodeVideoSse,
|
|
@@ -23,8 +24,8 @@ import {
|
|
|
23
24
|
sanitizeVideoChatMedia,
|
|
24
25
|
videoSseHeaders,
|
|
25
26
|
withDeadline
|
|
26
|
-
} from "./chunk-
|
|
27
|
-
import "./chunk-
|
|
27
|
+
} from "./chunk-HKUI5BTB.js";
|
|
28
|
+
import "./chunk-RXTN2CW6.js";
|
|
28
29
|
import {
|
|
29
30
|
allowedKeys,
|
|
30
31
|
createClippedVariableWarning,
|
|
@@ -32,28 +33,26 @@ import {
|
|
|
32
33
|
jsonValue,
|
|
33
34
|
nonNegativeInteger,
|
|
34
35
|
parseVideoEvent,
|
|
36
|
+
parseVideoPlanPart,
|
|
35
37
|
record,
|
|
36
38
|
safePublicDiagnostic,
|
|
37
39
|
string
|
|
38
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-7M56IUUX.js";
|
|
39
41
|
import {
|
|
40
42
|
MAX_RETAINED_MEDIA_URL_LENGTH
|
|
41
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-AUPC6MDK.js";
|
|
42
44
|
import {
|
|
43
45
|
VIDEO_PROTOCOL_VERSION
|
|
44
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-7NZOMTAL.js";
|
|
45
47
|
import {
|
|
46
48
|
createTemplateSystemPrompt,
|
|
47
49
|
getStandardMediaResolverContract
|
|
48
|
-
} from "./chunk-
|
|
49
|
-
import "./chunk-
|
|
50
|
-
import "./chunk-
|
|
51
|
-
import "./chunk-
|
|
50
|
+
} from "./chunk-OR52UMSF.js";
|
|
51
|
+
import "./chunk-PAJ44TFW.js";
|
|
52
|
+
import "./chunk-EGVQODKU.js";
|
|
53
|
+
import "./chunk-LH4BPALA.js";
|
|
52
54
|
import "./chunk-3O7OMMMF.js";
|
|
53
55
|
import "./chunk-2E6T633S.js";
|
|
54
|
-
import {
|
|
55
|
-
validateBrandInput
|
|
56
|
-
} from "./chunk-XGRA2MUV.js";
|
|
57
56
|
import "./chunk-73NTSFFI.js";
|
|
58
57
|
|
|
59
58
|
// src/server/request-validation.ts
|
|
@@ -109,7 +108,6 @@ function parseVideoRequest(value) {
|
|
|
109
108
|
"orientation",
|
|
110
109
|
"style",
|
|
111
110
|
"opening",
|
|
112
|
-
"brand",
|
|
113
111
|
"personalization",
|
|
114
112
|
"suppliedMedia",
|
|
115
113
|
"audio"
|
|
@@ -224,7 +222,6 @@ function parseVideoRequest(value) {
|
|
|
224
222
|
);
|
|
225
223
|
}
|
|
226
224
|
}
|
|
227
|
-
if (input.brand != null) validateBrandInput(input.brand, "request.input.brand");
|
|
228
225
|
jsonValue(input, "request.input");
|
|
229
226
|
if (request.capabilities != null) capabilities(request.capabilities, "request.capabilities");
|
|
230
227
|
if (request.resume != null) {
|
|
@@ -473,7 +470,8 @@ function fallbackVariables(variables) {
|
|
|
473
470
|
delete fallback.mediaKeyword;
|
|
474
471
|
delete fallback.mediaUrl;
|
|
475
472
|
delete fallback.mediaPoster;
|
|
476
|
-
fallback.mediaType
|
|
473
|
+
delete fallback.mediaType;
|
|
474
|
+
delete fallback.mediaSource;
|
|
477
475
|
return fallback;
|
|
478
476
|
}
|
|
479
477
|
async function resolveVariables(options) {
|
|
@@ -559,7 +557,18 @@ async function resolvePartVariables(options) {
|
|
|
559
557
|
scene: options.part.scene,
|
|
560
558
|
variables: options.part.scene.variables
|
|
561
559
|
});
|
|
562
|
-
|
|
560
|
+
if (options.templateId === "cinemaMedia" && !variables.mediaUrl) {
|
|
561
|
+
const title = variables.fallbackText;
|
|
562
|
+
if (typeof title !== "string" || !title.trim() || [...title].length > 65) {
|
|
563
|
+
throw new Error("A media scene without a usable asset requires grounded fallbackText (1\u201365 characters)");
|
|
564
|
+
}
|
|
565
|
+
return { ...options.part, scene: { ...options.part.scene, templateId: "chapterTitle", variables: { title: title.trim() } } };
|
|
566
|
+
}
|
|
567
|
+
const rendered = { ...variables };
|
|
568
|
+
delete rendered.mediaSource;
|
|
569
|
+
delete rendered.fallbackText;
|
|
570
|
+
delete rendered.shotDirection;
|
|
571
|
+
return { ...options.part, scene: { ...options.part.scene, variables: rendered } };
|
|
563
572
|
}
|
|
564
573
|
return options.part;
|
|
565
574
|
}
|
|
@@ -579,6 +588,25 @@ function createMediaResolvingPlanner(options) {
|
|
|
579
588
|
}
|
|
580
589
|
return false;
|
|
581
590
|
};
|
|
591
|
+
const preflight = (part) => {
|
|
592
|
+
try {
|
|
593
|
+
parseVideoPlanPart(part);
|
|
594
|
+
if (part.type === "scene.add") {
|
|
595
|
+
const { templateId, variables } = part.scene;
|
|
596
|
+
if (context.request.capabilities?.templates && !context.request.capabilities.templates.includes(templateId)) {
|
|
597
|
+
throw new Error(`Scene template ${templateId} was not negotiated`);
|
|
598
|
+
}
|
|
599
|
+
const template = options.templates.getTemplateMetadata(templateId);
|
|
600
|
+
if (!template) throw new Error(`Template ${templateId} is not installed`);
|
|
601
|
+
validateTemplateSceneStructure(template.schema, variables, true);
|
|
602
|
+
}
|
|
603
|
+
return true;
|
|
604
|
+
} catch (cause) {
|
|
605
|
+
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
606
|
+
if (!getGenerationLifecycleSink(context)?.rejectPart?.(error)) throw error;
|
|
607
|
+
return false;
|
|
608
|
+
}
|
|
609
|
+
};
|
|
582
610
|
const resolveOne = (part, openingReady2) => resolvePartVariables({
|
|
583
611
|
part,
|
|
584
612
|
requestId: context.request.requestId,
|
|
@@ -598,7 +626,9 @@ function createMediaResolvingPlanner(options) {
|
|
|
598
626
|
})
|
|
599
627
|
});
|
|
600
628
|
if (limit === 1) {
|
|
601
|
-
for await (const part of options.planner(context))
|
|
629
|
+
for await (const part of options.planner(context)) {
|
|
630
|
+
if (preflight(part)) yield await resolveOne(part);
|
|
631
|
+
}
|
|
602
632
|
return;
|
|
603
633
|
}
|
|
604
634
|
let openingReady = options.isOpeningReady(context.request.input);
|
|
@@ -631,6 +661,7 @@ function createMediaResolvingPlanner(options) {
|
|
|
631
661
|
const next = await iterator.next();
|
|
632
662
|
if (next.done || consumerClosed) break;
|
|
633
663
|
const part = next.value;
|
|
664
|
+
if (!preflight(part)) continue;
|
|
634
665
|
pending.push(resolveOne(part, openingReady).then(
|
|
635
666
|
(resolved) => ({ part: resolved }),
|
|
636
667
|
(cause) => ({ cause })
|
|
@@ -680,6 +711,7 @@ function clipText(value, maxLength) {
|
|
|
680
711
|
}
|
|
681
712
|
function boundValue(value, schema) {
|
|
682
713
|
if (!schema) return value;
|
|
714
|
+
if (schema.format === "grounded-stat" || schema.format === "grounded-quote") return value;
|
|
683
715
|
if (typeof value === "string") {
|
|
684
716
|
return typeof schema.maxLength === "number" ? clipText(value, schema.maxLength) : value;
|
|
685
717
|
}
|
|
@@ -707,10 +739,10 @@ function createBoundedVariablePlanner(options) {
|
|
|
707
739
|
}
|
|
708
740
|
try {
|
|
709
741
|
const lifecycle = getGenerationLifecycleSink(context);
|
|
710
|
-
if (!options.templates.getTemplateMetadata(part.scene.templateId) && lifecycle?.recoverGeneratedParts && (context.request.capabilities?.templates == null || context.request.capabilities.templates.includes("
|
|
742
|
+
if (!options.templates.getTemplateMetadata(part.scene.templateId) && lifecycle?.recoverGeneratedParts && (context.request.capabilities?.templates == null || context.request.capabilities.templates.includes("chapterTitle"))) {
|
|
711
743
|
const copy = [part.scene.variables.texts, part.scene.variables.title, part.scene.variables.message, part.scene.narration].find((value) => typeof value === "string" && Boolean(value.trim()) && !/https?:\/\/|\b(?:api[_-]?key|authorization|secret|token|password)\s*[:=]/i.test(value));
|
|
712
744
|
if (copy) {
|
|
713
|
-
part = { ...part, scene: { ...part.scene, templateId: "
|
|
745
|
+
part = { ...part, scene: { ...part.scene, templateId: "chapterTitle", variables: { title: copy } } };
|
|
714
746
|
lifecycle.reportWarning?.({ code: "provider_warning", category: "provider", message: "Some scenes use a simpler layout.", recoverable: true });
|
|
715
747
|
}
|
|
716
748
|
}
|
|
@@ -830,30 +862,19 @@ function createVideoHandler(options) {
|
|
|
830
862
|
}
|
|
831
863
|
|
|
832
864
|
// src/server/video-chat-prompts.ts
|
|
833
|
-
|
|
834
|
-
function createVideoChatResponseInstructions(fullAiVideo, openingAlreadyProvided = false, maxGeneratedVideos = 5) {
|
|
865
|
+
function createVideoChatResponseInstructions(generatedVideoAvailable, openingAlreadyProvided = false, maxGeneratedVideos = 5) {
|
|
835
866
|
return [
|
|
836
|
-
"
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
"
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
"
|
|
845
|
-
"
|
|
846
|
-
"
|
|
847
|
-
"5. Close on the payoff or the one thing worth carrying forward, never a recap.",
|
|
848
|
-
"No scene may repeat another scene's job. If a scene could be deleted without weakening the response, replace it.",
|
|
849
|
-
"The prompt is already on screen, so never spend the opening scene restating it.",
|
|
850
|
-
"If the input includes an OPENING ALREADY SPOKEN transcript, continue directly from that exact hook. Never repeat, paraphrase, contradict, or render it as the first scene's copy.",
|
|
851
|
-
"For factual requests, distinguish supplied facts from stable general knowledge and never invent statistics, quotations, sources, or personal experience.",
|
|
852
|
-
"For creative requests, create the requested material directly rather than explaining how one might create it.",
|
|
853
|
-
fullAiVideo ? "Use the media template for every scene you emit. Every scene must set mediaType to video and carry a mediaKeyword: a concrete, filmable subject, a real object doing a real thing, never a diagram or an abstraction. Never use mediaType gradient and never omit mediaKeyword - a scene without one has nothing to film. If a beat seems too abstract to film, film the closest real thing that shows it." : "Choose the template that fits each beat honestly - a figure belongs in a number scene, an ordered process in steps, a comparison in a chart - rather than repeating one shape. Give any scene that would be stronger over real footage a mediaKeyword: a concrete, filmable subject, a real object doing a real thing, never a diagram or an abstraction. Use the media template for the one or two beats most worth watching happen.",
|
|
854
|
-
fullAiVideo ? 'Mark the final scene placement:"closer". Use the media template for it, as for every other beat.' : 'Mark the final scene placement:"closer" and use either the milestone or the media template for it. Those are the only two here that may close, so the response must end on one.',
|
|
855
|
-
"Every scene must carry a timing object, even an empty one. A scene without it fails the whole response.",
|
|
856
|
-
"Never mention the video, the scenes, or yourself."
|
|
867
|
+
"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 spoken sentence","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
|
+
openingAlreadyProvided ? "Preserve the supplied opening exactly; continue it without repeating its words or claim." : void 0,
|
|
870
|
+
"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
|
+
"For concrete topics, coherent footage carries the story and graphics clarify particular points. Maintain consistent setting, lighting and subject while varying shot scale. Avoid unrelated cinematic montages.",
|
|
872
|
+
"Use the installed catalog: parallel points, ordered events, comparison, exact quote, one key figure, chapter or a message only when its narrative job fits. Do not force every template into a video. Avoid repeating the same graphic or more than two consecutive graphic scenes unless necessary.",
|
|
873
|
+
`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
|
+
"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
|
+
"No invented quotations, attribution, statistics, personal evidence or URLs. Creative stories may be invented when requested; do not present generated illustration as historical evidence.",
|
|
876
|
+
'Emit exactly one final placement:"closer" scene using a catalog template with a suitable payoff or ask job. It should land the meaning, not recap the whole answer.',
|
|
877
|
+
"Every scene needs timing, even an empty object. Narration forms one continuous spoken explanation, uses natural sentence lengths, and does not read every on-screen word back. Finish with plan.complete."
|
|
857
878
|
].filter((line) => line != null).join("\n");
|
|
858
879
|
}
|
|
859
880
|
var VIDEO_CHAT_NARRATION_PROMPT = [
|
|
@@ -944,10 +965,10 @@ function boundedString2(value, label, maximum = MAX_PROMPT_CHARACTERS) {
|
|
|
944
965
|
}
|
|
945
966
|
function parseResponseRequest(value) {
|
|
946
967
|
const body = record2(value, "request");
|
|
947
|
-
allowedKeys2(body, ["prompt", "opening", "mode", "orientation", "conversation", "
|
|
948
|
-
const mode = body.mode ?? "
|
|
949
|
-
if (mode !== "
|
|
950
|
-
throw new Error("request.mode must be
|
|
968
|
+
allowedKeys2(body, ["prompt", "opening", "mode", "orientation", "conversation", "style"], "request");
|
|
969
|
+
const mode = body.mode ?? "cinematic";
|
|
970
|
+
if (mode !== "cinematic") {
|
|
971
|
+
throw new Error("request.mode must be cinematic");
|
|
951
972
|
}
|
|
952
973
|
const orientation = body.orientation ?? "landscape";
|
|
953
974
|
if (orientation !== "portrait" && orientation !== "landscape") {
|
|
@@ -970,7 +991,6 @@ function parseResponseRequest(value) {
|
|
|
970
991
|
...turn.response == null ? {} : { response: boundedString2(turn.response, `request.conversation[${index}].response`, MAX_CONVERSATION_RESPONSE_CHARACTERS) }
|
|
971
992
|
};
|
|
972
993
|
}),
|
|
973
|
-
...body.brand == null ? {} : { brand: body.brand },
|
|
974
994
|
...body.style == null ? {} : { style: body.style }
|
|
975
995
|
};
|
|
976
996
|
}
|
|
@@ -1015,10 +1035,11 @@ function readGeneratedFirstShot(value) {
|
|
|
1015
1035
|
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1016
1036
|
const shot = value;
|
|
1017
1037
|
const bounded = (field, maximum) => typeof field === "string" ? [...field.trim()].slice(0, maximum).join("").trim() : "";
|
|
1018
|
-
const text = bounded(shot.text,
|
|
1038
|
+
const text = bounded(shot.text, 65);
|
|
1019
1039
|
const narration = bounded(shot.narration, 300);
|
|
1020
1040
|
const mediaKeyword = bounded(shot.mediaKeyword, 80).match(/\S+/gu)?.slice(0, 8).join(" ") ?? "";
|
|
1021
|
-
|
|
1041
|
+
const shotDirection = bounded(shot.shotDirection, 220);
|
|
1042
|
+
return text && narration && mediaKeyword ? { text, narration, mediaKeyword, ...shotDirection ? { shotDirection } : {} } : void 0;
|
|
1022
1043
|
}
|
|
1023
1044
|
function boundedWords(value, maximum, characters) {
|
|
1024
1045
|
if (typeof value !== "string") return "";
|
|
@@ -1044,9 +1065,11 @@ function reservedFirstScene(requestId, firstShot) {
|
|
|
1044
1065
|
type: "scene.add",
|
|
1045
1066
|
scene: {
|
|
1046
1067
|
id: `${requestId}-first-shot`,
|
|
1047
|
-
templateId: "
|
|
1068
|
+
templateId: "cinemaMedia",
|
|
1048
1069
|
variables: {
|
|
1049
|
-
|
|
1070
|
+
fallbackText: firstShot.text,
|
|
1071
|
+
mediaSource: "generate",
|
|
1072
|
+
...firstShot.shotDirection ? { shotDirection: firstShot.shotDirection } : {},
|
|
1050
1073
|
mediaType: "video",
|
|
1051
1074
|
mediaKeyword: firstShot.mediaKeyword
|
|
1052
1075
|
},
|
|
@@ -1102,7 +1125,7 @@ function interceptOpeningPlan(source, options) {
|
|
|
1102
1125
|
decided = true;
|
|
1103
1126
|
if (opening) {
|
|
1104
1127
|
if (!options.openingProvided) options.publish(opening.line ? opening : void 0);
|
|
1105
|
-
if (options.
|
|
1128
|
+
if (options.generatedVideoAvailable && opening.firstShot) {
|
|
1106
1129
|
yield `${JSON.stringify(reservedFirstScene(options.requestId, opening.firstShot))}
|
|
1107
1130
|
`;
|
|
1108
1131
|
}
|
|
@@ -1123,7 +1146,7 @@ function interceptOpeningPlan(source, options) {
|
|
|
1123
1146
|
decided = true;
|
|
1124
1147
|
if (opening) {
|
|
1125
1148
|
if (!options.openingProvided) options.publish(opening.line ? opening : void 0);
|
|
1126
|
-
if (options.
|
|
1149
|
+
if (options.generatedVideoAvailable && opening.firstShot) {
|
|
1127
1150
|
yield `${JSON.stringify(reservedFirstScene(options.requestId, opening.firstShot))}
|
|
1128
1151
|
`;
|
|
1129
1152
|
}
|
|
@@ -1303,21 +1326,20 @@ function createVideoChatHandler(options) {
|
|
|
1303
1326
|
generatedVideo: generateVideo != null,
|
|
1304
1327
|
stockMedia: searchMedia != null,
|
|
1305
1328
|
transcription: transcribe != null,
|
|
1306
|
-
modes:
|
|
1329
|
+
modes: ["cinematic"]
|
|
1307
1330
|
};
|
|
1308
1331
|
const welcomePrompts = (welcomeOptions?.prompts ?? DEFAULT_WELCOME_PROMPTS).slice(0, 4);
|
|
1309
1332
|
const heroQuery = welcomeOptions?.heroQuery;
|
|
1310
1333
|
let welcomeResponse;
|
|
1311
1334
|
let requestSequence = 0;
|
|
1312
|
-
const responseHandler = (
|
|
1313
|
-
const
|
|
1314
|
-
const fullAiVideo = mode === "full";
|
|
1335
|
+
const responseHandler = (requestId, openingProvided, openingChannel) => {
|
|
1336
|
+
const generatedVideoAvailable = generateVideo != null && maxGeneratedVideos > 0;
|
|
1315
1337
|
let lifecycle;
|
|
1316
1338
|
let generatedAttempts = 0;
|
|
1317
1339
|
const completedVideos = /* @__PURE__ */ new Map();
|
|
1318
1340
|
const reusedUrls = /* @__PURE__ */ new Set();
|
|
1319
1341
|
const resolveSelected = generateVideo || searchMedia ? async (query, context) => {
|
|
1320
|
-
const reuseKey = JSON.stringify([query, context.generatedLook ?? ""]);
|
|
1342
|
+
const reuseKey = JSON.stringify([query, context.generatedLook ?? "", context.scene.variables.shotDirection ?? "", context.input.orientation ?? "landscape"]);
|
|
1321
1343
|
const remember = (media) => {
|
|
1322
1344
|
if (media?.type === "video") completedVideos.set(reuseKey, media);
|
|
1323
1345
|
return media;
|
|
@@ -1349,7 +1371,7 @@ function createVideoChatHandler(options) {
|
|
|
1349
1371
|
return null;
|
|
1350
1372
|
}
|
|
1351
1373
|
};
|
|
1352
|
-
if (
|
|
1374
|
+
if (generatedVideoAvailable && context.scene.variables.mediaSource === "generate") {
|
|
1353
1375
|
const generated = generatedAttempts < maxGeneratedVideos ? (generatedAttempts++, await attempt(generateVideo, generateVideoTimeoutMs)) : null;
|
|
1354
1376
|
if (generated) return remember(generated);
|
|
1355
1377
|
lifecycle?.reportWarning?.({
|
|
@@ -1361,7 +1383,7 @@ function createVideoChatHandler(options) {
|
|
|
1361
1383
|
}
|
|
1362
1384
|
const stock = await attempt(searchMedia, 3e3);
|
|
1363
1385
|
if (stock) return remember(stock);
|
|
1364
|
-
if (
|
|
1386
|
+
if (generatedVideoAvailable) {
|
|
1365
1387
|
const previous = completedVideos.get(reuseKey);
|
|
1366
1388
|
if (previous && !reusedUrls.has(previous.url)) {
|
|
1367
1389
|
reusedUrls.add(previous.url);
|
|
@@ -1376,10 +1398,10 @@ function createVideoChatHandler(options) {
|
|
|
1376
1398
|
lifecycle = getGenerationLifecycleSink(context);
|
|
1377
1399
|
try {
|
|
1378
1400
|
return interceptOpeningPlan(videoOptions.streamText(context), {
|
|
1379
|
-
expectOpening:
|
|
1401
|
+
expectOpening: generatedVideoAvailable || !openingProvided,
|
|
1380
1402
|
openingProvided,
|
|
1381
1403
|
requestId,
|
|
1382
|
-
|
|
1404
|
+
generatedVideoAvailable,
|
|
1383
1405
|
publish: openingChannel.publish
|
|
1384
1406
|
});
|
|
1385
1407
|
} catch (cause) {
|
|
@@ -1392,7 +1414,7 @@ function createVideoChatHandler(options) {
|
|
|
1392
1414
|
allowCredentials,
|
|
1393
1415
|
maxBodyBytes,
|
|
1394
1416
|
mediaConcurrency,
|
|
1395
|
-
basePrompt: [createVideoChatResponseInstructions(
|
|
1417
|
+
basePrompt: [createVideoChatResponseInstructions(generatedVideoAvailable, openingProvided, maxGeneratedVideos), instructions?.trim()].filter(Boolean).join("\n\nAPPLICATION GUIDANCE\n"),
|
|
1396
1418
|
narrate: true,
|
|
1397
1419
|
resolveMedia: resolveSelected
|
|
1398
1420
|
});
|
|
@@ -1518,8 +1540,6 @@ function createVideoChatHandler(options) {
|
|
|
1518
1540
|
} catch (cause) {
|
|
1519
1541
|
return jsonError2(400, "invalid_request", cause instanceof Error ? cause.message : "Request is invalid", headers);
|
|
1520
1542
|
}
|
|
1521
|
-
const mode = input.mode !== "templates" && !generateVideo ? "templates" : input.mode;
|
|
1522
|
-
const fullAiVideo = mode === "full";
|
|
1523
1543
|
const requestId = `video-chat-${Date.now()}-${requestSequence += 1}`;
|
|
1524
1544
|
const openingChannel = createOpeningChannel(input.opening ? { line: input.opening, keyword: "" } : void 0);
|
|
1525
1545
|
const forwardedHeaders = new Headers(request.headers);
|
|
@@ -1529,16 +1549,14 @@ function createVideoChatHandler(options) {
|
|
|
1529
1549
|
headers: forwardedHeaders,
|
|
1530
1550
|
signal: request.signal,
|
|
1531
1551
|
body: JSON.stringify({
|
|
1532
|
-
protocolVersion:
|
|
1552
|
+
protocolVersion: VIDEO_PROTOCOL_VERSION,
|
|
1533
1553
|
requestId,
|
|
1534
|
-
...fullAiVideo ? { capabilities: { templates: ["media"] } } : {},
|
|
1535
1554
|
input: {
|
|
1536
1555
|
input: conversationInput(input.prompt, input.conversation, input.opening),
|
|
1537
1556
|
knowledgeMode: "general",
|
|
1538
1557
|
opening: false,
|
|
1539
1558
|
orientation: input.orientation,
|
|
1540
1559
|
maxDurationSec: 40,
|
|
1541
|
-
...input.brand ? { brand: input.brand } : {},
|
|
1542
1560
|
style: {
|
|
1543
1561
|
density: "airy",
|
|
1544
1562
|
motion: "calm",
|
|
@@ -1549,7 +1567,6 @@ function createVideoChatHandler(options) {
|
|
|
1549
1567
|
})
|
|
1550
1568
|
});
|
|
1551
1569
|
const response = await responseHandler(
|
|
1552
|
-
mode,
|
|
1553
1570
|
requestId,
|
|
1554
1571
|
input.opening != null,
|
|
1555
1572
|
openingChannel
|