@vanillaskyai/video 0.5.8 → 0.7.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 +178 -0
- package/PUBLIC-API.md +129 -9
- package/README.md +70 -108
- package/dist/{bg-confetti-SHQI7ATB.js → bg-confetti-HITCGLGD.js} +1 -1
- package/dist/{bg-emoji-XYFRA63Q.js → bg-emoji-VU4UZYZN.js} +1 -1
- package/dist/{bg-media-FEBATBT2.js → bg-media-L34PDQXJ.js} +4 -4
- package/dist/{brand-message-P56WEJPG.js → brand-message-FUJ4STFO.js} +3 -3
- package/dist/{builtin-server-YHEZ2JRF.js → builtin-server-KB7FKF6A.js} +2 -2
- package/dist/{chart-bar-ZB45ZRKH.js → chart-bar-EGPHJATL.js} +4 -4
- package/dist/{chart-counter-HFYNE4HT.js → chart-counter-5FFWQNZO.js} +4 -4
- package/dist/{chart-progress-ring-ZKMLRGSB.js → chart-progress-ring-JMXQLMLC.js} +4 -4
- package/dist/check-runtime.js +2 -2
- package/dist/{chunk-66MNRUCR.js → chunk-2PYO6VAC.js} +51 -3
- package/dist/{chunk-ZQQQAAKP.js → chunk-2XT4MZ76.js} +33 -2
- package/dist/chunk-5CDAM24P.js +31 -0
- package/dist/{chunk-PNS52FL4.js → chunk-5SLENAJW.js} +19 -6
- package/dist/{chunk-EFL34TXF.js → chunk-AITKH6QT.js} +24 -8
- package/dist/{chunk-HT6BGERF.js → chunk-FRN6WKHA.js} +28 -10
- package/dist/{chunk-FZHMQFG3.js → chunk-GAIOHGNR.js} +5 -21
- package/dist/{chunk-3RV4YKB3.js → chunk-JNN3EYVP.js} +51 -26
- package/dist/{chunk-NGY3TNND.js → chunk-K746NUIP.js} +70 -50
- package/dist/{chunk-HVCPEAQF.js → chunk-LKBZX7GV.js} +9 -6
- package/dist/{chunk-G66Z5CWR.js → chunk-MMUXVA47.js} +27 -3
- package/dist/{chunk-6M6DATLW.js → chunk-MXZSDGZQ.js} +6 -5
- package/dist/{chunk-3OU7HIEB.js → chunk-RE4IMWJR.js} +15 -31
- package/dist/{chunk-FVTMYS6U.js → chunk-RGF452LL.js} +1 -1
- package/dist/{chunk-34O5BY6X.js → chunk-RXHW4EP4.js} +21 -4
- package/dist/chunk-SKRGRKHY.js +142 -0
- package/dist/{chunk-TCEHK2BW.js → chunk-YJJC4N4D.js} +2 -1
- package/dist/cli.js +438 -30
- package/dist/{compose-video-JWIEDTEJ.js → compose-video-PD6LKKRK.js} +4 -4
- package/dist/{cta-logo-S4OMTNXD.js → cta-logo-YR7LYUR5.js} +3 -3
- package/dist/{cta-media-EROTHDRR.js → cta-media-DQJBKUO2.js} +4 -4
- package/dist/{events-BBP30j3c.d.ts → events-B6qS1Lsb.d.ts} +2 -2
- package/dist/{incoming-call-5IWJ2TAS.js → incoming-call-54KQ7O5A.js} +3 -3
- package/dist/index.d.ts +89 -3
- package/dist/index.js +12 -1
- package/dist/{infographic-before-after-2I7YZVDD.js → infographic-before-after-ROS52GOW.js} +1 -1
- package/dist/{infographic-feature-list-7SK65U3K.js → infographic-feature-list-E7MGUDAN.js} +4 -4
- package/dist/{infographic-problem-solution-IW35S6BR.js → infographic-problem-solution-3S6NGO5N.js} +4 -4
- package/dist/{infographic-stat-row-XHUZZPDM.js → infographic-stat-row-SYB7AB7H.js} +4 -4
- package/dist/{infographic-steps-JDDEDI7X.js → infographic-steps-KCE6JWE2.js} +4 -4
- package/dist/{kit-DEG3fcaL.d.ts → kit-8g46H2RZ.d.ts} +1 -1
- package/dist/{prompt-input-6ZWXEL3V.js → prompt-input-MHX4O42G.js} +3 -3
- package/dist/react.d.ts +200 -6
- package/dist/react.js +1859 -43
- package/dist/{reaction-Z3JIM3MQ.js → reaction-SLEGR3BE.js} +4 -4
- package/dist/{scene-video-backdrop-IL4F2SVD.js → scene-video-backdrop-XFPX4O3I.js} +2 -1
- package/dist/server.d.ts +104 -4
- package/dist/server.js +976 -26
- package/dist/{showcase-code-NWQAAJIA.js → showcase-code-2HLAVKBM.js} +4 -4
- package/dist/{showcase-phone-5UW45ATT.js → showcase-phone-Q4HEO4LH.js} +4 -4
- package/dist/{showcase-terminal-UVOD25UF.js → showcase-terminal-DL45LUFG.js} +4 -4
- package/dist/{showcase-web-3AW6VHIG.js → showcase-web-2QZO73FZ.js} +4 -4
- package/dist/{social-milestone-KPKHFOB5.js → social-milestone-GEFUQSBF.js} +3 -3
- package/dist/{social-notification-EDOU6TZB.js → social-notification-FJ5VHVLK.js} +3 -3
- package/dist/{social-review-stack-EZOO33SV.js → social-review-stack-KXQCKFRP.js} +3 -3
- package/dist/{social-testimonial-DLOINMMY.js → social-testimonial-JZ7CHC7S.js} +3 -3
- package/dist/{social-tweet-6JUM323G.js → social-tweet-UCDXM25F.js} +3 -3
- package/dist/{system-prompt-4I6Z5HK3.js → system-prompt-RRXIWDDD.js} +5 -3
- package/dist/template-catalog.js +1 -1
- package/dist/templates.d.ts +3 -3
- package/dist/test.d.ts +2 -2
- package/dist/test.js +3 -3
- package/dist/{text-stream-J6EDDJP4.js → text-stream-FW4BLBAL.js} +2 -2
- package/dist/{types-BV9IqExh.d.ts → types-2wHBqtg8.d.ts} +29 -1
- package/dist/types-DrABlRa7.d.ts +46 -0
- package/docs/agent-integration.md +49 -25
- package/docs/architecture.md +37 -22
- package/docs/branding-and-personalization.md +1 -1
- package/docs/concepts.md +14 -0
- package/docs/custom-templates.md +9 -9
- package/docs/customization.md +41 -5
- package/docs/getting-started.md +81 -84
- package/docs/media-and-audio.md +113 -117
- package/docs/persistence.md +1 -1
- package/docs/production.md +81 -92
- package/docs/prompt-and-input.md +71 -161
- package/docs/provider-integration.md +91 -49
- package/docs/responsive-orientation.md +1 -1
- package/docs/security.md +6 -5
- package/docs/streaming-protocol.md +1 -1
- package/docs/testing.md +51 -43
- package/examples/custom-template/README.md +1 -1
- package/package.json +20 -21
- package/registry/items/backgrounds.json +2 -2
- package/registry/items/barChart.json +6 -4
- package/registry/items/beforeAfter.json +1 -1
- package/registry/items/bigNumber.json +4 -3
- package/registry/items/brandMessage.json +3 -2
- package/registry/items/cardList.json +6 -4
- package/registry/items/codeEditor.json +4 -3
- package/registry/items/confetti.json +1 -1
- package/registry/items/ctaLogo.json +3 -2
- package/registry/items/ctaMedia.json +4 -3
- package/registry/items/emojiBurst.json +1 -1
- package/registry/items/incomingCall.json +3 -2
- package/registry/items/media.json +4 -3
- package/registry/items/milestone.json +3 -2
- package/registry/items/notification.json +3 -2
- package/registry/items/phoneMockup.json +4 -3
- package/registry/items/problemSolution.json +4 -3
- package/registry/items/progressRing.json +4 -3
- package/registry/items/promptInput.json +3 -2
- package/registry/items/reaction.json +2 -2
- package/registry/items/reviewStack.json +3 -2
- package/registry/items/steps.json +6 -4
- package/registry/items/terminal.json +5 -4
- package/registry/items/testimonial.json +3 -2
- package/registry/items/tripleStats.json +4 -3
- package/registry/items/tweet.json +3 -2
- package/registry/items/webMockup.json +4 -3
- package/starters/video-chat/.env.example +16 -0
- package/starters/video-chat/README.md +63 -0
- package/starters/video-chat/index.html +12 -0
- package/starters/video-chat/package.json +28 -0
- package/starters/video-chat/server.ts +152 -0
- package/starters/video-chat/src/main.tsx +8 -0
- package/starters/video-chat/stock.ts +139 -0
- package/starters/video-chat/tsconfig.json +20 -0
- package/starters/video-chat/vite.config.ts +81 -0
- package/styles/video-chat.css +713 -0
- package/dist/chunk-C6WVCZRW.js +0 -19
- package/docs/input-and-first-scene.md +0 -64
- package/docs/integrate-nextjs.md +0 -86
- package/docs/live-channels.md +0 -149
- package/docs/use-cases.md +0 -59
- package/examples/nextjs-quickstart/.env.example +0 -2
- package/examples/nextjs-quickstart/README.md +0 -27
- package/examples/nextjs-quickstart/next-env.d.ts +0 -4
- package/examples/nextjs-quickstart/package.json +0 -25
- package/examples/nextjs-quickstart/src/app/api/video/route.ts +0 -24
- package/examples/nextjs-quickstart/src/app/layout.tsx +0 -5
- package/examples/nextjs-quickstart/src/app/page.tsx +0 -31
- package/examples/nextjs-quickstart/tsconfig.json +0 -26
package/docs/custom-templates.md
CHANGED
|
@@ -24,28 +24,28 @@ List the effective catalog, including project-owned templates, before choosing
|
|
|
24
24
|
what to build or copy:
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
npx vanillasky list
|
|
27
|
+
npx vanillasky templates list
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
Create an original template:
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
npx vanillasky create customer-health
|
|
34
|
-
npx vanillasky describe customer-health
|
|
33
|
+
npx vanillasky templates create customer-health
|
|
34
|
+
npx vanillasky templates describe customer-health
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
Or copy a built-in when its behavior is already close:
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
|
-
npx vanillasky add bigNumber
|
|
40
|
+
npx vanillasky templates add bigNumber
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
Then edit the owned `.tsx` file, regenerate the two small registries, and check
|
|
44
44
|
the complete contract:
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
|
-
npx vanillasky sync
|
|
48
|
-
npx vanillasky check
|
|
47
|
+
npx vanillasky templates sync
|
|
48
|
+
npx vanillasky templates check
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
For an original template, the source is
|
|
@@ -62,8 +62,8 @@ registry parity.
|
|
|
62
62
|
Preview either operation without applying the proposed file writes:
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
|
-
npx vanillasky add bigNumber --dry-run
|
|
66
|
-
npx vanillasky add bigNumber --diff
|
|
65
|
+
npx vanillasky templates add bigNumber --dry-run
|
|
66
|
+
npx vanillasky templates add bigNumber --diff
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
`--dry-run` lists every proposed file and `--diff` shows its content changes,
|
|
@@ -79,7 +79,7 @@ An edited file is never replaced unless you explicitly pass `--overwrite`.
|
|
|
79
79
|
|
|
80
80
|
## One file is the contract
|
|
81
81
|
|
|
82
|
-
The file created by `vanillasky create` is a complete working template. Keep
|
|
82
|
+
The file created by `vanillasky templates create` is a complete working template. Keep
|
|
83
83
|
these concerns together:
|
|
84
84
|
|
|
85
85
|
- `useWhen` and `avoidWhen` tell the AI when the visual is appropriate;
|
package/docs/customization.md
CHANGED
|
@@ -2,6 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
# Customization
|
|
4
4
|
|
|
5
|
+
## Video chat interface
|
|
6
|
+
|
|
7
|
+
The default `VideoChat` interface is already responsive and accessible. Pass a
|
|
8
|
+
custom welcome heading and a root class when the application needs its own copy
|
|
9
|
+
or chrome colors:
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
<VideoChat
|
|
13
|
+
className="acme-chat"
|
|
14
|
+
welcomeTitle={<>Ask Acme<br />See the answer</>}
|
|
15
|
+
options={{ brand: acmeBrand }}
|
|
16
|
+
/>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Override the scoped custom properties after importing
|
|
20
|
+
`@vanillaskyai/video/video-chat.css`; the selectors and values stay local to
|
|
21
|
+
that instance:
|
|
22
|
+
|
|
23
|
+
```css
|
|
24
|
+
.acme-chat {
|
|
25
|
+
--vs-accent: #0057ff;
|
|
26
|
+
--vs-accent-deep: #003fb8;
|
|
27
|
+
--vs-voice: #e11d74;
|
|
28
|
+
--vs-font: "Inter", sans-serif;
|
|
29
|
+
--vs-radius-lg: 1rem;
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Use `options` for the endpoint, templates, orientation, visual brand, request
|
|
34
|
+
headers, and an optional custom voice. Provider capabilities are discovered
|
|
35
|
+
from the server. Use `useVideoChat()` only when the application needs to own the
|
|
36
|
+
entire interface.
|
|
37
|
+
|
|
38
|
+
The sections below customize lower-level, one-shot video composition. They are
|
|
39
|
+
not required for the default chat.
|
|
40
|
+
|
|
5
41
|
## Background and semantic brand
|
|
6
42
|
|
|
7
43
|
Omit brand configuration to use the standard `cosmic` background. Prefer a
|
|
@@ -125,16 +161,16 @@ Pass `audio: { src }` for a specific track, omit `audio` to let the server choos
|
|
|
125
161
|
synchronously from a preloaded catalog, or pass `audio: false` for silence.
|
|
126
162
|
VanillaSky infers deterministic duration, volume, beat, and fade-out metadata.
|
|
127
163
|
The soundtrack should continue across visual generation gaps and finish with
|
|
128
|
-
the final scene.
|
|
129
|
-
|
|
164
|
+
the final scene. `VideoChat` separately owns narration, TTS integration, browser
|
|
165
|
+
voice fallback, and speech synchronization for conversational responses.
|
|
130
166
|
|
|
131
167
|
## Custom templates
|
|
132
168
|
|
|
133
169
|
The built-in catalog needs no setup. Only source-owned templates need the
|
|
134
170
|
optional local TSX compiler; install it once with `npm install --save-dev tsx`.
|
|
135
|
-
Then use `npx vanillasky create <id>` for an original one-file template or
|
|
136
|
-
`npx vanillasky add <builtin>` to copy a close built-in. Edit the owned file,
|
|
137
|
-
run `npx vanillasky sync`, then run `npx vanillasky check` before committing.
|
|
171
|
+
Then use `npx vanillasky templates create <id>` for an original one-file template or
|
|
172
|
+
`npx vanillasky templates add <builtin>` to copy a close built-in. Edit the owned file,
|
|
173
|
+
run `npx vanillasky templates sync`, then run `npx vanillasky templates check` before committing.
|
|
138
174
|
Pass the generated registry to the server and browser; project-owned IDs
|
|
139
175
|
replace matching built-ins and new IDs extend the catalog.
|
|
140
176
|
|
package/docs/getting-started.md
CHANGED
|
@@ -1,109 +1,106 @@
|
|
|
1
|
-
[← Documentation home](../README.md) · [
|
|
1
|
+
[← Documentation home](../README.md) · [Next: Provider integration →](provider-integration.md)
|
|
2
2
|
|
|
3
3
|
# Getting started
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The fastest VanillaSky integration is the complete, general-purpose video chat.
|
|
6
|
+
It starts with packaged templates and browser voice, then turns on optional
|
|
7
|
+
speech, stock, transcription, and generated video when their server keys exist.
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
npm install @vanillaskyai/video
|
|
9
|
-
```
|
|
9
|
+
## Create the app
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Create one authenticated server route with `createVideoHandler`. Connect the
|
|
17
|
-
app-owned model through `streamText`; keep credentials, authentication, rate
|
|
18
|
-
limits, and media policy on the server:
|
|
19
|
-
|
|
20
|
-
```ts
|
|
21
|
-
import { streamText } from "ai";
|
|
22
|
-
import { createVideoHandler } from "@vanillaskyai/video/server";
|
|
23
|
-
import { videoModel } from "@/lib/video-model";
|
|
24
|
-
|
|
25
|
-
const handle = createVideoHandler({
|
|
26
|
-
// Local development only. Replace with your session check before deploying.
|
|
27
|
-
authorize: (request) => {
|
|
28
|
-
if (process.env.VANILLASKY_LOCAL_DEMO !== "1") return false;
|
|
29
|
-
const hostname = new URL(request.url).hostname;
|
|
30
|
-
return hostname === "localhost" || hostname === "127.0.0.1";
|
|
31
|
-
},
|
|
32
|
-
streamText: ({ systemPrompt, userPrompt, signal }) => streamText({
|
|
33
|
-
model: videoModel,
|
|
34
|
-
system: systemPrompt,
|
|
35
|
-
prompt: userPrompt,
|
|
36
|
-
abortSignal: signal,
|
|
37
|
-
}),
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
export const POST = handle;
|
|
41
|
-
export const OPTIONS = handle;
|
|
11
|
+
Start in an empty folder:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx @vanillaskyai/video init
|
|
42
15
|
```
|
|
43
16
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
before deploying. For literal files and commands,
|
|
48
|
-
use the tested [`examples/nextjs-quickstart` directory](../examples/nextjs-quickstart).
|
|
17
|
+
Init installs the exact SDK version that ran it, creates a small application
|
|
18
|
+
shell, and installs its provider dependencies.
|
|
19
|
+
It does not copy VanillaSky's template tree. The important generated files are:
|
|
49
20
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
21
|
+
| File | Your application owns |
|
|
22
|
+
| --- | --- |
|
|
23
|
+
| `src/main.tsx` | The mount point for the SDK-owned chat |
|
|
24
|
+
| `server.ts` | Provider choices and callbacks |
|
|
25
|
+
| `stock.ts` | Optional stock search policy |
|
|
26
|
+
| `vite.config.ts` | Local UI and `/api/video-chat` endpoint |
|
|
27
|
+
| `.env.local` | Ignored server-only credentials |
|
|
53
28
|
|
|
54
|
-
|
|
29
|
+
The generated browser entry is intentionally tiny:
|
|
55
30
|
|
|
56
31
|
```tsx
|
|
57
|
-
|
|
32
|
+
import { StrictMode } from "react";
|
|
33
|
+
import { createRoot } from "react-dom/client";
|
|
34
|
+
import { VideoChat } from "@vanillaskyai/video/react";
|
|
35
|
+
import "@vanillaskyai/video/video-chat.css";
|
|
36
|
+
|
|
37
|
+
createRoot(document.getElementById("root")!).render(
|
|
38
|
+
<StrictMode><VideoChat /></StrictMode>,
|
|
39
|
+
);
|
|
40
|
+
```
|
|
58
41
|
|
|
59
|
-
|
|
42
|
+
The SDK owns the responsive interface, conversation state, suggestions, voice
|
|
43
|
+
input, narration pacing, streaming player, and packaged templates. Your shell
|
|
44
|
+
stays responsible for providers, keys, authorization, limits, storage,
|
|
45
|
+
branding, and product copy.
|
|
60
46
|
|
|
61
|
-
|
|
62
|
-
const video = useVideo();
|
|
47
|
+
## Add the one required key
|
|
63
48
|
|
|
64
|
-
|
|
65
|
-
<button onClick={() => { void video.generate({ input }); }}>Generate video</button>
|
|
66
|
-
{video.error && <p role="alert">Video generation failed.</p>}
|
|
67
|
-
<VideoPlayer {...video.playerProps} />
|
|
68
|
-
</>;
|
|
69
|
-
}
|
|
70
|
-
```
|
|
49
|
+
Add the text-provider key to the generated, ignored `.env.local`:
|
|
71
50
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
51
|
+
```dotenv
|
|
52
|
+
ANTHROPIC_API_KEY=
|
|
53
|
+
```
|
|
75
54
|
|
|
76
|
-
|
|
77
|
-
|
|
55
|
+
Fill the value locally; do not expose it through a client-prefixed environment
|
|
56
|
+
variable. Then inspect the setup without calling any provider:
|
|
78
57
|
|
|
79
|
-
```
|
|
80
|
-
|
|
58
|
+
```bash
|
|
59
|
+
npx vanillasky doctor
|
|
81
60
|
```
|
|
82
61
|
|
|
83
|
-
The
|
|
84
|
-
|
|
85
|
-
reactive UI.
|
|
62
|
+
The base experience reports `templates + browser voice`. A ready text key makes
|
|
63
|
+
the chat answer. Optional keys progressively add capabilities:
|
|
86
64
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
stops at a planner length limit includes a `plan_incomplete` warning because
|
|
91
|
-
requested scenes or the ending may be missing. Provider finish reasons and
|
|
92
|
-
content-filter details remain available to the server through the `onComplete`
|
|
93
|
-
summary; surface that server-owned state separately when completeness matters
|
|
94
|
-
to your product.
|
|
65
|
+
```dotenv
|
|
66
|
+
# Optional generated speech
|
|
67
|
+
XAI_API_KEY=
|
|
95
68
|
|
|
96
|
-
|
|
97
|
-
|
|
69
|
+
# Optional generated video and voice transcription
|
|
70
|
+
FAL_KEY=
|
|
98
71
|
|
|
99
|
-
|
|
100
|
-
|
|
72
|
+
# Optional stock media
|
|
73
|
+
PEXELS_API_KEY=
|
|
101
74
|
```
|
|
102
75
|
|
|
103
|
-
|
|
104
|
-
|
|
76
|
+
Doctor reports only key names and readiness, never values. Adding or removing
|
|
77
|
+
an optional key changes the available modes after a server restart; the client
|
|
78
|
+
does not need to change.
|
|
79
|
+
|
|
80
|
+
## Run and verify
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npm run dev
|
|
84
|
+
```
|
|
105
85
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
86
|
+
Open the reported localhost URL. Try one explanatory question and one unrelated
|
|
87
|
+
creative request in the same conversation. Confirm each response starts with a
|
|
88
|
+
spoken hook from the response stream before the full plan is complete, holds its opening until the first
|
|
89
|
+
scene is ready, reaches its final frame, and leaves the composer ready for
|
|
90
|
+
another turn. With stock media enabled, click a welcome or follow-up card and
|
|
91
|
+
confirm its footage carries directly into that opening. With generated video
|
|
92
|
+
enabled, confirm the only choices are Templates and Full AI video and that the
|
|
93
|
+
first generated shot continues the spoken hook without repeating it.
|
|
94
|
+
|
|
95
|
+
The generated local authorization accepts localhost only. Replace it with your
|
|
96
|
+
real session check, rate limits, and usage policy before deploying.
|
|
97
|
+
|
|
98
|
+
## Continue
|
|
99
|
+
|
|
100
|
+
- Change providers or add media capabilities in [Provider integration](provider-integration.md).
|
|
101
|
+
- Brand or reshape the default experience in [Customization](customization.md).
|
|
102
|
+
- Use a fully custom UI with the headless chat hook described in
|
|
103
|
+
[Provider integration](provider-integration.md#custom-interface).
|
|
104
|
+
- Copy and edit a visual only when needed in [Custom templates](custom-templates.md).
|
|
105
|
+
- Apply production authorization and key handling from
|
|
106
|
+
[Production](production.md) and [Security](security.md).
|
package/docs/media-and-audio.md
CHANGED
|
@@ -1,139 +1,135 @@
|
|
|
1
1
|
[← Documentation home](../README.md) · [Previous: Branding and personalization](branding-and-personalization.md) · [Next: Custom templates →](custom-templates.md)
|
|
2
2
|
|
|
3
|
-
# Media and
|
|
3
|
+
# Media, voice, and audio
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
VanillaSky keeps provider choice in the application. The SDK defines small
|
|
6
|
+
server callbacks, advertises only the capabilities you configure, and keeps
|
|
7
|
+
all credentials out of React and the browser bundle.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
If a product needs spoken audio, the application must create and synchronize
|
|
11
|
-
that experience outside this contract.
|
|
9
|
+
## Two visual modes
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
`suppliedMedia`, or configure the server-only `resolveMedia` callback for
|
|
15
|
-
planner-selected backgrounds. Preload the next scene's asset before it becomes
|
|
16
|
-
active. Keep provider credentials on the server.
|
|
11
|
+
The chat exposes only two clear choices:
|
|
17
12
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
require the completed video to use it.
|
|
13
|
+
| Mode | Visual source | Required callback |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `templates` | Trusted rendered templates, optionally with stock footage | none; `searchMedia` is optional |
|
|
16
|
+
| `full` | A generated clip for every visual beat | `generateVideo` |
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
defaults. Hosting and licensing are the application's responsibility.
|
|
18
|
+
Templates are always available and are the fast, inexpensive fallback. The
|
|
19
|
+
`full` mode is advertised only when `generateVideo` exists. VanillaSky does not
|
|
20
|
+
offer a mixed mode that generates only some scenes.
|
|
28
21
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
`
|
|
22
|
+
## Stock media for templates
|
|
23
|
+
|
|
24
|
+
Add `searchMedia` when template answers, the welcome screen, and follow-up
|
|
25
|
+
cards should use approved photography or footage:
|
|
32
26
|
|
|
33
27
|
```ts
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
28
|
+
createVideoChatHandler({
|
|
29
|
+
authorize: verifySession,
|
|
30
|
+
streamText: planWithYourModel,
|
|
31
|
+
generateText: runSmallTextTask,
|
|
32
|
+
searchMedia: async (query, { purpose, orientation, signal }) => {
|
|
33
|
+
const asset = await searchApprovedCatalog({
|
|
34
|
+
query,
|
|
35
|
+
purpose,
|
|
36
|
+
orientation,
|
|
37
|
+
signal,
|
|
38
|
+
});
|
|
39
|
+
return asset
|
|
40
|
+
? { url: asset.url, type: asset.type, posterUrl: asset.posterUrl }
|
|
41
|
+
: null;
|
|
42
|
+
},
|
|
43
|
+
});
|
|
39
44
|
```
|
|
40
45
|
|
|
41
|
-
The
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
to guarantee a silent video.
|
|
46
|
+
The planner emits a short semantic keyword, not a URL. The callback returns an
|
|
47
|
+
application-approved image or video URL, and the SDK validates it before it
|
|
48
|
+
reaches a scene. Return `null` when no licensed, safe, relevant asset exists;
|
|
49
|
+
the template falls back to its built-in treatment.
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
For Pexels, keep `PEXELS_API_KEY` on the server, enforce a deadline, filter for
|
|
52
|
+
orientation, and return only validated Pexels asset domains. Licensing,
|
|
53
|
+
attribution, caching, MIME checks, and byte limits remain application-owned.
|
|
50
54
|
|
|
51
|
-
##
|
|
55
|
+
## Full generated video
|
|
52
56
|
|
|
53
|
-
|
|
54
|
-
the
|
|
55
|
-
visible and let the player's start control provide that interaction:
|
|
56
|
-
|
|
57
|
-
```tsx
|
|
58
|
-
<VideoPlayer
|
|
59
|
-
{...video.playerProps}
|
|
60
|
-
playbackMode="autoplay-after-interaction"
|
|
61
|
-
/>
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
The generation cover immediately includes a centered **Play with sound**
|
|
65
|
-
button. A click starts the soundtrack and holds that branded cover as a
|
|
66
|
-
three-second generation intro while planning continues. Once both the intro
|
|
67
|
-
and the first validated scene are ready, the generated timeline begins from
|
|
68
|
-
time zero. The generation intro remains visible indefinitely if the viewer has
|
|
69
|
-
not clicked yet, even when the complete generated video is already ready. The
|
|
70
|
-
server keeps the generated first scene on screen for at least three more
|
|
71
|
-
seconds when the duration budget permits. After that first successful sound start,
|
|
72
|
-
replacement streams on the same mounted player autoplay the same generation
|
|
73
|
-
intro with sound and fall back to a start control if the browser blocks them.
|
|
74
|
-
|
|
75
|
-
When `VideoInput.opening` is supplied, its asset-free gradient `media` scene
|
|
76
|
-
replaces the generic generation cover as soon as it is available. It remains
|
|
77
|
-
as the static start poster until the viewer clicks, then begins the actual
|
|
78
|
-
timeline with sound; there is no additional generic pre-roll before it.
|
|
79
|
-
|
|
80
|
-
Use `playbackMode="manual"` to require the button on every run,
|
|
81
|
-
`playbackMode="muted-autoplay"` for browser-safe muted autoplay, or
|
|
82
|
-
`playbackMode="autoplay-with-sound"` to try audible autoplay immediately. The
|
|
83
|
-
lower-level `autoPlay` and `startMuted` props remain available when no playback
|
|
84
|
-
mode is set. For a chat response that should try audible autoplay without the
|
|
85
|
-
SDK generation intro, pass `opening: false`, wait to mount the player until a
|
|
86
|
-
generated scene exists, and render it with `autoPlay` and `startMuted={false}`.
|
|
87
|
-
If the browser blocks the audible start, the player returns to the first frame
|
|
88
|
-
and exposes its sound-start control.
|
|
89
|
-
|
|
90
|
-
For a saved video rendered with `<VideoPlayer video={video} loop />`, the
|
|
91
|
-
soundtrack loops too. A track shorter than the visual timeline repeats without
|
|
92
|
-
a silent gap, and the player restarts it from the beginning when the visual
|
|
93
|
-
timeline wraps. This does not bypass browser autoplay policy: use muted autoplay
|
|
94
|
-
for unattended playback and let a viewer unmute, or start audible playback from
|
|
95
|
-
a user interaction.
|
|
96
|
-
|
|
97
|
-
## Media providers
|
|
98
|
-
|
|
99
|
-
VanillaSky is provider-independent. When `resolveMedia` is configured, the
|
|
100
|
-
built-in planner may emit a bounded semantic query for later media-capable
|
|
101
|
-
scenes. The SDK calls the application-owned resolver on the server, replaces
|
|
102
|
-
the query with the approved URL, type, and optional poster, then validates the
|
|
103
|
-
scene before emitting it. Without the callback, media intent stays hidden from
|
|
104
|
-
the planner. The first accepted generated scene remains asset-free.
|
|
57
|
+
Add `generateVideo` to enable full AI video. It receives the planned visual
|
|
58
|
+
subject plus the generated look so every clip can follow the same direction:
|
|
105
59
|
|
|
106
60
|
```ts
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
createVideoHandler({
|
|
110
|
-
authorize: checkSession,
|
|
61
|
+
createVideoChatHandler({
|
|
62
|
+
authorize: verifySession,
|
|
111
63
|
streamText: planWithYourModel,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
64
|
+
generateText: runSmallTextTask,
|
|
65
|
+
generateVideo: async (subject, {
|
|
66
|
+
generatedLook,
|
|
67
|
+
orientation,
|
|
68
|
+
requestId,
|
|
69
|
+
scene,
|
|
70
|
+
signal,
|
|
71
|
+
}) => {
|
|
72
|
+
const asset = await generateAndStore({
|
|
73
|
+
subject,
|
|
74
|
+
generatedLook,
|
|
75
|
+
orientation,
|
|
76
|
+
requestId,
|
|
77
|
+
sceneId: scene?.id,
|
|
78
|
+
signal,
|
|
79
|
+
maxRetries: 0,
|
|
80
|
+
});
|
|
81
|
+
return asset ? { url: asset.url, type: "video" } : null;
|
|
117
82
|
},
|
|
118
83
|
});
|
|
119
84
|
```
|
|
120
85
|
|
|
121
|
-
The
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
86
|
+
The first streamed object reserves the first generated shot while the same
|
|
87
|
+
model call continues planning later scenes. Use `requestId` and `scene.id` as
|
|
88
|
+
an idempotency key, because generated clips are billable. Keep `maxRetries: 0`
|
|
89
|
+
inside provider calls, honour `signal`, and make retries an explicit product
|
|
90
|
+
decision with a known budget.
|
|
91
|
+
|
|
92
|
+
VanillaSky does not depend on a video model or storage service. The application
|
|
93
|
+
owns the provider key, model, spend, generated bytes, retention, and delivery.
|
|
94
|
+
|
|
95
|
+
## Voice and transcription
|
|
96
|
+
|
|
97
|
+
Without `generateSpeech`, `VideoChat` uses the browser voice. Add a speech
|
|
98
|
+
callback for a consistent generated voice:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
generateSpeech: async ({ text, signal }) => {
|
|
102
|
+
const speech = await synthesize(text, { signal });
|
|
103
|
+
return { audio: speech.bytes, mediaType: speech.mediaType };
|
|
104
|
+
},
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The SDK measures or estimates each line, keeps narration synchronized with the
|
|
108
|
+
picture, and prevents a new scene from replacing speech that is still playing.
|
|
109
|
+
If generated speech fails, the interface can fall back to browser speech.
|
|
110
|
+
|
|
111
|
+
Add `transcribe` for server-side microphone transcription when browser speech
|
|
112
|
+
recognition is unavailable. Set `maxAudioBytes`, validate the media type, and
|
|
113
|
+
apply a provider deadline.
|
|
114
|
+
|
|
115
|
+
## Native clip audio and soundtrack
|
|
116
|
+
|
|
117
|
+
Generated clips can contain diegetic audio. The chat player keeps that audio
|
|
118
|
+
separate from narration and uses one master mute control. Avoid generated
|
|
119
|
+
voiceover or music inside clips so it does not compete with the answer voice.
|
|
120
|
+
|
|
121
|
+
A serialized `Video` can also contain an application-owned soundtrack for
|
|
122
|
+
replay or custom playback. Soundtrack files, licenses, beat markers, volume,
|
|
123
|
+
and fade-out remain host-owned; narration and speech synchronization remain
|
|
124
|
+
the chat layer's responsibility. Browser autoplay rules still require a viewer
|
|
125
|
+
interaction before audible playback on many devices.
|
|
126
|
+
|
|
127
|
+
## Safety rules
|
|
128
|
+
|
|
129
|
+
- Keep every provider key in server-only environment variables.
|
|
130
|
+
- Never let a planner return arbitrary final media URLs.
|
|
131
|
+
- Bound query length, response size, duration, concurrency, and generated spend.
|
|
132
|
+
- Preload the next asset and keep the current visual when media is late.
|
|
133
|
+
- Return a safe fallback instead of leaving the response waiting forever.
|
|
134
|
+
|
|
135
|
+
[← Documentation home](../README.md) · [Previous: Branding and personalization](branding-and-personalization.md) · [Next: Custom templates →](custom-templates.md)
|
package/docs/persistence.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[← Documentation home](../README.md) · [Previous: Core concepts](concepts.md) · [Next:
|
|
1
|
+
[← Documentation home](../README.md) · [Previous: Core concepts](concepts.md) · [Next: Streaming protocol →](streaming-protocol.md)
|
|
2
2
|
|
|
3
3
|
# Persistence and replay
|
|
4
4
|
|