@vanillaskyai/video 0.7.1 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/PUBLIC-API.md +83 -79
  3. package/README.md +20 -15
  4. package/dist/assets/vanillasky-logo.svg +151 -0
  5. package/dist/{builtin-server-KB7FKF6A.js → builtin-server-CUYPIDE7.js} +2 -2
  6. package/dist/check-runtime.js +1 -1
  7. package/dist/{chunk-2PYO6VAC.js → chunk-2DOLF4QN.js} +1 -43
  8. package/dist/{chunk-GAIOHGNR.js → chunk-2OKB27TG.js} +42 -45
  9. package/dist/{chunk-K746NUIP.js → chunk-2USVB3CY.js} +80 -29
  10. package/dist/{chunk-RE4IMWJR.js → chunk-3VRMKFM7.js} +87 -14
  11. package/dist/{chunk-JNN3EYVP.js → chunk-4UNKZEAT.js} +46 -46
  12. package/dist/{chunk-2XT4MZ76.js → chunk-APQKY6P3.js} +36 -3
  13. package/dist/{chunk-LLPMVDJZ.js → chunk-L7QGGKJ2.js} +69 -38
  14. package/dist/{chunk-RGF452LL.js → chunk-OWBT45EN.js} +1 -1
  15. package/dist/{chunk-LKBZX7GV.js → chunk-PP3MCPN4.js} +4 -4
  16. package/dist/chunk-ZD2VTUYR.js +28 -0
  17. package/dist/cli.js +131 -24
  18. package/dist/{compose-video-PD6LKKRK.js → compose-video-2NFH4DZY.js} +3 -3
  19. package/dist/{events-B6qS1Lsb.d.ts → events-BQ6z264n.d.ts} +1 -1
  20. package/dist/index.d.ts +5 -67
  21. package/dist/index.js +2 -4
  22. package/dist/{kit-8g46H2RZ.d.ts → kit-tQnCPMOM.d.ts} +1 -1
  23. package/dist/react.d.ts +33 -53
  24. package/dist/react.js +982 -648
  25. package/dist/server.d.ts +11 -13
  26. package/dist/server.js +170 -81
  27. package/dist/template-catalog.js +1 -1
  28. package/dist/templates.d.ts +3 -3
  29. package/dist/test.d.ts +2 -2
  30. package/dist/test.js +3 -3
  31. package/dist/{text-stream-ROTNGSD4.js → text-stream-54LXABJW.js} +1 -1
  32. package/dist/{types-2wHBqtg8.d.ts → types-CEh9eUFu.d.ts} +1 -1
  33. package/dist/{types-DrABlRa7.d.ts → types-DWFO6qca.d.ts} +1 -1
  34. package/docs/agent-integration.md +9 -3
  35. package/docs/architecture.md +8 -10
  36. package/docs/concepts.md +16 -40
  37. package/docs/custom-templates.md +27 -23
  38. package/docs/customization.md +23 -55
  39. package/docs/errors.md +58 -68
  40. package/docs/getting-started.md +21 -14
  41. package/docs/immersive-interface.md +87 -0
  42. package/docs/media-and-audio.md +2 -2
  43. package/docs/performance.md +69 -0
  44. package/docs/persistence.md +12 -27
  45. package/docs/production.md +2 -2
  46. package/docs/provider-integration.md +11 -5
  47. package/docs/reference/design-system.html +115 -0
  48. package/docs/reference/provider-adapters.md +37 -89
  49. package/docs/security.md +1 -1
  50. package/docs/streaming-protocol.md +2 -2
  51. package/examples/custom-template/README.md +6 -6
  52. package/package.json +6 -7
  53. package/registry/items/barChart.json +2 -2
  54. package/registry/items/bigNumber.json +2 -2
  55. package/registry/items/brandMessage.json +2 -2
  56. package/registry/items/cardList.json +2 -2
  57. package/registry/items/codeEditor.json +2 -2
  58. package/registry/items/ctaLogo.json +2 -2
  59. package/registry/items/ctaMedia.json +2 -2
  60. package/registry/items/incomingCall.json +2 -2
  61. package/registry/items/media.json +2 -2
  62. package/registry/items/milestone.json +2 -2
  63. package/registry/items/notification.json +2 -2
  64. package/registry/items/phoneMockup.json +2 -2
  65. package/registry/items/problemSolution.json +2 -2
  66. package/registry/items/progressRing.json +2 -2
  67. package/registry/items/promptInput.json +2 -2
  68. package/registry/items/reaction.json +2 -2
  69. package/registry/items/reviewStack.json +2 -2
  70. package/registry/items/steps.json +2 -2
  71. package/registry/items/terminal.json +2 -2
  72. package/registry/items/testimonial.json +2 -2
  73. package/registry/items/tripleStats.json +2 -2
  74. package/registry/items/tweet.json +2 -2
  75. package/registry/items/webMockup.json +2 -2
  76. package/starters/video-chat/.env.example +4 -2
  77. package/starters/video-chat/README.md +17 -5
  78. package/starters/video-chat/index.html +2 -1
  79. package/starters/video-chat/package.json +2 -4
  80. package/starters/video-chat/providers/speech.ts +20 -0
  81. package/starters/video-chat/providers/video.ts +66 -0
  82. package/starters/video-chat/providers.ts +3 -0
  83. package/starters/video-chat/server.ts +4 -80
  84. package/starters/video-chat/stock.ts +114 -99
  85. package/styles/video-chat.css +650 -246
  86. package/dist/chunk-SKRGRKHY.js +0 -142
  87. package/dist/state-DZcKuS32.d.ts +0 -3
  88. package/docs/branding-and-personalization.md +0 -87
  89. package/examples/custom-template/supplied-media.tsx +0 -92
@@ -1,142 +0,0 @@
1
- import {
2
- checksumVideo,
3
- createVideoEventFactory
4
- } from "./chunk-2PYO6VAC.js";
5
- import {
6
- VIDEO_SCHEMA_VERSION
7
- } from "./chunk-AOWSXU2K.js";
8
- import {
9
- getReadableSceneDuration
10
- } from "./chunk-3O7OMMMF.js";
11
-
12
- // src/protocol/scene-timeline.ts
13
- function createQueue() {
14
- const buffered = [];
15
- const waiting = [];
16
- let closed = false;
17
- return {
18
- push(value) {
19
- const next = waiting.shift();
20
- if (next) next({ value, done: false });
21
- else buffered.push(value);
22
- },
23
- close() {
24
- closed = true;
25
- let next = waiting.shift();
26
- while (next) {
27
- next({ value: void 0, done: true });
28
- next = waiting.shift();
29
- }
30
- },
31
- iterable: {
32
- [Symbol.asyncIterator]() {
33
- return {
34
- next() {
35
- const buffer = buffered.shift();
36
- if (buffer !== void 0) return Promise.resolve({ value: buffer, done: false });
37
- if (closed) return Promise.resolve({ value: void 0, done: true });
38
- return new Promise((resolve) => waiting.push(resolve));
39
- }
40
- };
41
- }
42
- }
43
- };
44
- }
45
- var runCounter = 0;
46
- function createSceneTimeline(options) {
47
- const queue = createQueue();
48
- const runId = options.runId ?? `composed-${runCounter += 1}`;
49
- const events = createVideoEventFactory({ runId });
50
- const orientation = options.orientation ?? "landscape";
51
- const snapshot = {
52
- schemaVersion: VIDEO_SCHEMA_VERSION,
53
- orientation,
54
- scenes: [],
55
- style: options.style
56
- };
57
- let position = 0;
58
- let finished = false;
59
- const held = [];
60
- let openForScenes = !options.awaitAudio;
61
- const emit = (event) => {
62
- if (finished) return;
63
- queue.push(event);
64
- };
65
- emit(events.create("response.start", {
66
- requestId: options.requestId ?? runId,
67
- format: { orientation },
68
- style: options.style
69
- }));
70
- if (options.audio) {
71
- snapshot.audio = options.audio;
72
- emit(events.create("audio.set", { audio: options.audio }));
73
- }
74
- const release = () => {
75
- const pending = held.splice(0, held.length);
76
- for (const scene of pending) {
77
- snapshot.scenes.push(scene);
78
- emit(events.create("scene.add", { scene, position: position++ }));
79
- }
80
- };
81
- return {
82
- stream: queue.iterable,
83
- add(scene) {
84
- if (finished) return;
85
- if (!openForScenes) {
86
- held.push(scene);
87
- return;
88
- }
89
- snapshot.scenes.push(scene);
90
- emit(events.create("scene.add", { scene, position: position++ }));
91
- },
92
- setAudio(audio) {
93
- if (finished || openForScenes) return;
94
- if (audio) {
95
- snapshot.audio = audio;
96
- emit(events.create("audio.set", { audio }));
97
- }
98
- openForScenes = true;
99
- release();
100
- },
101
- complete() {
102
- if (finished) return;
103
- if (!openForScenes) {
104
- openForScenes = true;
105
- release();
106
- }
107
- emit(events.create("response.complete", {
108
- finishReason: "stop",
109
- snapshot,
110
- checksum: checksumVideo(snapshot)
111
- }));
112
- finished = true;
113
- queue.close();
114
- }
115
- };
116
- }
117
-
118
- // src/protocol/scene-duration.ts
119
- var NARRATION_WORDS_PER_SECOND = 2.6;
120
- var NARRATION_TAIL_SECONDS = 0.6;
121
- function getSceneDurationBounds(scene, metadata) {
122
- return {
123
- minimum: Math.max(1e-3, metadata?.minDuration ?? 1),
124
- readable: getReadableSceneDuration(scene, metadata)
125
- };
126
- }
127
- function getSpokenDuration(narration) {
128
- const words = narration.trim().split(/\s+/u).filter(Boolean).length;
129
- if (words === 0) return 0;
130
- return words / NARRATION_WORDS_PER_SECOND + NARRATION_TAIL_SECONDS;
131
- }
132
- function getSceneDuration(scene, metadata) {
133
- const { readable } = getSceneDurationBounds(scene, metadata);
134
- return Math.max(readable, scene.narration ? getSpokenDuration(scene.narration) : 0);
135
- }
136
-
137
- export {
138
- createSceneTimeline,
139
- getSceneDurationBounds,
140
- getSpokenDuration,
141
- getSceneDuration
142
- };
@@ -1,3 +0,0 @@
1
- type VideoStatus = "idle" | "streaming" | "complete" | "error" | "aborted";
2
-
3
- export type { VideoStatus as V };
@@ -1,87 +0,0 @@
1
- [← Documentation home](../README.md) · [Previous: Prompt and conversation input](prompt-and-input.md) · [Next: Media and audio →](media-and-audio.md)
2
-
3
- # Branding and personalization
4
-
5
- Brand values style the whole response. Personalization shapes who the story is for.
6
-
7
- ## Background: standard, preset, or custom
8
-
9
- Do nothing to use the standard `cosmic` background:
10
-
11
- ```ts
12
- video.generate({ input });
13
- ```
14
-
15
- Choose a curated gradient or solid by name when the standard does not fit:
16
-
17
- ```ts
18
- video.generate({
19
- input,
20
- brand: { background: "twilight" },
21
- });
22
- ```
23
-
24
- Curated gradients are `cosmic`, `horizon`, `twilight`, `meadow`, `velvet`,
25
- `flamingo`, `peach`, and `saffron`. Curated solids are `black`, `midnight`,
26
- `aubergine`, `coal`, and `navy`.
27
-
28
- Use exact colors only when a real brand or campaign requires them:
29
-
30
- ```ts
31
- brand: { background: { colors: ["#112233", "#334455"] } } // gradient
32
- brand: { background: { color: "#070B20" } } // solid
33
- ```
34
-
35
- These choices set the background colors used by every trusted gradient-backed
36
- template and by the automatic generation cover. Templates own their
37
- composition and type treatment, so there is no separate visual-preset choice.
38
-
39
- ## Semantic brand tokens
40
-
41
- Most applications can stop at `brand.background` and `brand.font`. Supply
42
- semantic colors only when a real design system requires exact values:
43
-
44
- ```ts
45
- const brand = {
46
- name: "Acme Cloud",
47
- logoUrl: approvedLogoUrl,
48
- font: "Inter",
49
- scriptFont: "Caveat",
50
- background: "twilight",
51
- colors: {
52
- primary: "#7C5CFC",
53
- secondary: "#3D2A78",
54
- foreground: "#FFFFFF",
55
- surface: "#161229",
56
- surfaceElevated: "#211A38",
57
- muted: "#AAA5B8",
58
- },
59
- };
60
- ```
61
-
62
- Every generated video contains a fully resolved brand. `colors` may be partial
63
- on input; omitted values receive deterministic defaults. When
64
- `colors.foreground` is omitted, every named or custom background is paired
65
- deterministically with black or white. The resolver checks the full rendered
66
- sRGB gradient ramp, including interior blends rather than only its endpoints.
67
- If neither foreground reaches 4.5:1 everywhere, resolution rejects the
68
- background and asks for a consistently readable choice.
69
-
70
- An explicitly supplied foreground is preserved, never silently replaced. It
71
- must reach 4.5:1 across the solid background or entire gradient ramp; otherwise
72
- input resolution and replay validation reject it with the failing brand path
73
- and minimum contrast. Surface tokens remain independent. Templates that put
74
- text on `surface` or `surfaceElevated` internally keep an accessible preferred
75
- semantic text color or derive black/white for that surface.
76
-
77
- Use an approved public or signed URL for logos. Fonts must be licensed and
78
- loaded by the host application before playback. Always test both orientations
79
- and forced browser zoom.
80
-
81
- `personalization` accepts JSON-safe viewer or account context such as
82
- `firstName`, `role`, `accountName`, `locale`, `goal`, or `onboardingPartner`.
83
- These values may appear verbatim in the response, but are always data, never
84
- instructions. Put product, news, metric, and quoted claims in `input`; do not
85
- duplicate ordinary viewer context there.
86
-
87
- Only include information the authenticated viewer is allowed to see. Avoid sensitive HR, health, payment, or customer attributes in event logs and analytics. If a locale changes number/date formatting, format facts server-side so the planner cannot guess.
@@ -1,92 +0,0 @@
1
- import { defineTemplate } from "@vanillaskyai/video/templates";
2
-
3
- const previewImageUrl = "data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%221200%22%20height=%22720%22%20viewBox=%220%200%201200%20720%22%3E%3Crect%20width=%221200%22%20height=%22720%22%20rx=%2248%22%20fill=%22%23181733%22/%3E%3Crect%20x=%2280%22%20y=%2280%22%20width=%221040%22%20height=%22560%22%20rx=%2232%22%20fill=%22%23f4f1ff%22/%3E%3Ccircle%20cx=%22220%22%20cy=%22230%22%20r=%2270%22%20fill=%22%237867dd%22/%3E%3Cpath%20d=%22M160%20520L380%20360L580%20430L820%20220L1040%20300%22%20fill=%22none%22%20stroke=%22%23287b77%22%20stroke-width=%2232%22%20stroke-linecap=%22round%22%20stroke-linejoin=%22round%22/%3E%3C/svg%3E";
4
-
5
- export const template = defineTemplate({
6
- id: "supplied-media",
7
- label: "Supplied media",
8
- description: "An application-supplied screenshot with a grounded caption.",
9
- useWhen: "Use when a supplied product image is the strongest evidence for the answer.",
10
- avoidWhen: "Avoid when no approved image was supplied or text and data communicate the point more clearly.",
11
- schema: {
12
- type: "object",
13
- properties: {
14
- imageUrl: {
15
- type: "string",
16
- format: "supplied-image",
17
- title: "Supplied image",
18
- description: "The URL of an image present in VideoInput.suppliedMedia.",
19
- default: previewImageUrl,
20
- },
21
- headline: {
22
- type: "string",
23
- title: "Headline",
24
- minLength: 1,
25
- maxLength: 72,
26
- default: "See the change in context.",
27
- },
28
- caption: {
29
- type: "string",
30
- title: "Caption",
31
- minLength: 1,
32
- maxLength: 120,
33
- default: "The dashboard reflects the grounded result described in the answer.",
34
- },
35
- },
36
- required: ["imageUrl", "headline", "caption"],
37
- additionalProperties: false,
38
- } as const,
39
- examples: [{
40
- name: "Product dashboard",
41
- variables: {
42
- imageUrl: previewImageUrl,
43
- headline: "See the change in context.",
44
- caption: "The dashboard reflects the grounded result described in the answer.",
45
- },
46
- }],
47
- minDuration: 4,
48
- preferredDuration: 6,
49
- component: ({ variables, progress, width, height, safeZone }) => {
50
- const isPortrait = height >= width;
51
- const reveal = Math.max(0, Math.min(1, progress * 1.7));
52
-
53
- return <section style={{
54
- boxSizing: "border-box",
55
- width,
56
- height,
57
- padding: `${safeZone.top}px ${safeZone.right}px ${safeZone.bottom}px ${safeZone.left}px`,
58
- display: "grid",
59
- gridTemplateColumns: isPortrait ? "1fr" : "minmax(0, 1.1fr) minmax(320px, 0.9fr)",
60
- alignContent: "center",
61
- alignItems: "center",
62
- gap: isPortrait ? 44 : 64,
63
- overflow: "hidden",
64
- color: "#15152b",
65
- background: "linear-gradient(145deg, #f4f1ff, #dfe7ff)",
66
- fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif",
67
- }}>
68
- <img
69
- src={variables.imageUrl}
70
- alt=""
71
- style={{
72
- display: "block",
73
- width: "100%",
74
- maxHeight: isPortrait ? height * 0.48 : height * 0.68,
75
- objectFit: "cover",
76
- borderRadius: 28,
77
- boxShadow: "0 28px 80px rgba(28, 34, 75, 0.24)",
78
- opacity: reveal,
79
- transform: `scale(${0.96 + reveal * 0.04})`,
80
- }}
81
- />
82
- <div style={{ opacity: reveal }}>
83
- <h1 style={{ margin: 0, fontSize: isPortrait ? 58 : 70, lineHeight: 0.98, letterSpacing: "-0.045em" }}>
84
- {variables.headline}
85
- </h1>
86
- <p style={{ margin: "24px 0 0", fontSize: isPortrait ? 25 : 28, lineHeight: 1.4 }}>
87
- {variables.caption}
88
- </p>
89
- </div>
90
- </section>;
91
- },
92
- });