@vanillaskyai/video 0.5.8 → 0.6.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/PUBLIC-API.md +6 -0
  3. package/README.md +8 -0
  4. package/dist/{bg-media-FEBATBT2.js → bg-media-G4XOQEAS.js} +3 -3
  5. package/dist/{brand-message-P56WEJPG.js → brand-message-XHONEDNW.js} +3 -3
  6. package/dist/{chart-bar-ZB45ZRKH.js → chart-bar-HRHD57ML.js} +3 -3
  7. package/dist/{chart-counter-HFYNE4HT.js → chart-counter-KFPV44RB.js} +3 -3
  8. package/dist/{chart-progress-ring-ZKMLRGSB.js → chart-progress-ring-OR2VOIHV.js} +3 -3
  9. package/dist/check-runtime.js +2 -2
  10. package/dist/chunk-5CDAM24P.js +31 -0
  11. package/dist/{chunk-6M6DATLW.js → chunk-7BGAU6C3.js} +4 -4
  12. package/dist/{chunk-HT6BGERF.js → chunk-FRN6WKHA.js} +28 -10
  13. package/dist/{chunk-NGY3TNND.js → chunk-K746NUIP.js} +70 -50
  14. package/dist/{cta-logo-S4OMTNXD.js → cta-logo-JJOGK4UC.js} +3 -3
  15. package/dist/{cta-media-EROTHDRR.js → cta-media-IQ3MAWEH.js} +3 -3
  16. package/dist/{incoming-call-5IWJ2TAS.js → incoming-call-KXF67OT2.js} +3 -3
  17. package/dist/{infographic-feature-list-7SK65U3K.js → infographic-feature-list-QDM4I7XE.js} +3 -3
  18. package/dist/{infographic-problem-solution-IW35S6BR.js → infographic-problem-solution-FMLJCPG6.js} +3 -3
  19. package/dist/{infographic-stat-row-XHUZZPDM.js → infographic-stat-row-VFTIXS5F.js} +3 -3
  20. package/dist/{infographic-steps-JDDEDI7X.js → infographic-steps-L7W24Z35.js} +3 -3
  21. package/dist/{prompt-input-6ZWXEL3V.js → prompt-input-F3CYU2XH.js} +3 -3
  22. package/dist/react.d.ts +6 -0
  23. package/dist/react.js +33 -26
  24. package/dist/{reaction-Z3JIM3MQ.js → reaction-2XCLOJOK.js} +3 -3
  25. package/dist/{scene-video-backdrop-IL4F2SVD.js → scene-video-backdrop-XFPX4O3I.js} +2 -1
  26. package/dist/server.d.ts +2 -0
  27. package/dist/server.js +5 -0
  28. package/dist/{showcase-code-NWQAAJIA.js → showcase-code-KHSMIPG6.js} +3 -3
  29. package/dist/{showcase-phone-5UW45ATT.js → showcase-phone-M4CEANIW.js} +3 -3
  30. package/dist/{showcase-terminal-UVOD25UF.js → showcase-terminal-26I3DYF7.js} +3 -3
  31. package/dist/{showcase-web-3AW6VHIG.js → showcase-web-TY6CZV2Z.js} +3 -3
  32. package/dist/{social-milestone-KPKHFOB5.js → social-milestone-TF6MX7ET.js} +3 -3
  33. package/dist/{social-notification-EDOU6TZB.js → social-notification-2RJDAZSF.js} +3 -3
  34. package/dist/{social-review-stack-EZOO33SV.js → social-review-stack-2ICKJQG7.js} +3 -3
  35. package/dist/{social-testimonial-DLOINMMY.js → social-testimonial-X7OGADA3.js} +3 -3
  36. package/dist/{social-tweet-6JUM323G.js → social-tweet-TK7SH2F6.js} +3 -3
  37. package/docs/media-and-audio.md +59 -0
  38. package/examples/nextjs-quickstart/package.json +1 -1
  39. package/examples/nextjs-quickstart/src/app/api/video/route.ts +13 -4
  40. package/examples/server-integrations/README.md +20 -0
  41. package/examples/server-integrations/src/ai-sdk-media.ts +90 -0
  42. package/package.json +2 -1
  43. package/registry/items/backgrounds.json +2 -2
  44. package/dist/chunk-C6WVCZRW.js +0 -19
@@ -8,14 +8,14 @@ import {
8
8
  import {
9
9
  SceneBackground,
10
10
  getMediaBackgroundProps
11
- } from "./chunk-6M6DATLW.js";
11
+ } from "./chunk-7BGAU6C3.js";
12
12
  import {
13
13
  TemplateText
14
14
  } from "./chunk-TCEHK2BW.js";
15
15
  import {
16
16
  Emoji
17
17
  } from "./chunk-L5BTTCZV.js";
18
- import "./chunk-HT6BGERF.js";
18
+ import "./chunk-FRN6WKHA.js";
19
19
  import {
20
20
  TOP_TEXT_AREA_RATIO,
21
21
  autoTextColor,
@@ -25,10 +25,10 @@ import {
25
25
  interpolate,
26
26
  spring
27
27
  } from "./chunk-XTOXFMLM.js";
28
- import "./chunk-C6WVCZRW.js";
29
28
  import {
30
29
  hasSceneMedia
31
30
  } from "./chunk-224QNWRA.js";
31
+ import "./chunk-5CDAM24P.js";
32
32
  import {
33
33
  TOKEN_DEFAULTS,
34
34
  resolveTokens
@@ -4,8 +4,8 @@ import {
4
4
  import {
5
5
  SceneBackground,
6
6
  getMediaBackgroundProps
7
- } from "./chunk-6M6DATLW.js";
8
- import "./chunk-HT6BGERF.js";
7
+ } from "./chunk-7BGAU6C3.js";
8
+ import "./chunk-FRN6WKHA.js";
9
9
  import "./chunk-W3VDIBGR.js";
10
10
  import {
11
11
  SPRING_BOUNCY,
@@ -13,8 +13,8 @@ import {
13
13
  interpolate,
14
14
  spring
15
15
  } from "./chunk-XTOXFMLM.js";
16
- import "./chunk-C6WVCZRW.js";
17
16
  import "./chunk-224QNWRA.js";
17
+ import "./chunk-5CDAM24P.js";
18
18
  import {
19
19
  resolveTokens
20
20
  } from "./chunk-XWWLKRNU.js";
package/dist/react.d.ts CHANGED
@@ -7,12 +7,18 @@ import './catalog-types-BIhSpOWK.js';
7
7
 
8
8
  type VideoPlaybackMode = "manual" | "muted-autoplay" | "autoplay-with-sound" | "autoplay-after-interaction";
9
9
 
10
+ interface NativeMediaAudioOptions {
11
+ /** Volume of the active scene video's embedded audio, from 0 to 1. */
12
+ volume?: number;
13
+ }
10
14
  interface VideoPlayerSharedProps {
11
15
  /** High-level startup policy. When set, this overrides autoPlay and startMuted. */
12
16
  playbackMode?: VideoPlaybackMode;
13
17
  /** Initial playback state. Reduced-motion preferences take precedence. */
14
18
  autoPlay?: boolean;
15
19
  startMuted?: boolean;
20
+ /** Play embedded audio from active scene videos as a layer beneath the master mute control. */
21
+ nativeMediaAudio?: NativeMediaAudioOptions;
16
22
  /** Fixed display width. Omit to observe and fill the parent width. */
17
23
  width?: number;
18
24
  /** Override the streamed orientation, or switch at the container breakpoint. */
package/dist/react.js CHANGED
@@ -24,9 +24,9 @@ import {
24
24
  import {
25
25
  VideoFrame,
26
26
  getDimensions
27
- } from "./chunk-NGY3TNND.js";
28
- import "./chunk-C6WVCZRW.js";
27
+ } from "./chunk-K746NUIP.js";
29
28
  import "./chunk-224QNWRA.js";
29
+ import "./chunk-5CDAM24P.js";
30
30
  import {
31
31
  fontStack
32
32
  } from "./chunk-XWWLKRNU.js";
@@ -79,34 +79,34 @@ import { createElement } from "react";
79
79
 
80
80
  // src/visual-system/catalog/builtin-loaders.generated.ts
81
81
  var GENERATED_BUILTIN_TEMPLATE_LOADERS = {
82
- "media": () => import("./bg-media-FEBATBT2.js").then((module) => ({ default: module.BgMediaTemplate })),
83
- "reaction": () => import("./reaction-Z3JIM3MQ.js").then((module) => ({ default: module.ReactionTemplate })),
82
+ "media": () => import("./bg-media-G4XOQEAS.js").then((module) => ({ default: module.BgMediaTemplate })),
83
+ "reaction": () => import("./reaction-2XCLOJOK.js").then((module) => ({ default: module.ReactionTemplate })),
84
84
  "confetti": () => import("./bg-confetti-SHQI7ATB.js").then((module) => ({ default: module.BgConfettiTemplate })),
85
85
  "emojiBurst": () => import("./bg-emoji-XYFRA63Q.js").then((module) => ({ default: module.BgEmojiTemplate })),
86
- "bigNumber": () => import("./chart-counter-HFYNE4HT.js").then((module) => ({ default: module.ChartCounterTemplate })),
87
- "barChart": () => import("./chart-bar-ZB45ZRKH.js").then((module) => ({ default: module.ChartBarTemplate })),
88
- "progressRing": () => import("./chart-progress-ring-ZKMLRGSB.js").then((module) => ({ default: module.ChartProgressRingTemplate })),
89
- "phoneMockup": () => import("./showcase-phone-5UW45ATT.js").then((module) => ({ default: module.ShowcasePhoneTemplate })),
90
- "webMockup": () => import("./showcase-web-3AW6VHIG.js").then((module) => ({ default: module.ShowcaseWebTemplate })),
91
- "codeEditor": () => import("./showcase-code-NWQAAJIA.js").then((module) => ({ default: module.ShowcaseCodeTemplate })),
92
- "terminal": () => import("./showcase-terminal-UVOD25UF.js").then((module) => ({ default: module.ShowcaseTerminalTemplate })),
93
- "tweet": () => import("./social-tweet-6JUM323G.js").then((module) => ({ default: module.SocialTweetTemplate })),
94
- "notification": () => import("./social-notification-EDOU6TZB.js").then((module) => ({ default: module.SocialNotificationTemplate })),
86
+ "bigNumber": () => import("./chart-counter-KFPV44RB.js").then((module) => ({ default: module.ChartCounterTemplate })),
87
+ "barChart": () => import("./chart-bar-HRHD57ML.js").then((module) => ({ default: module.ChartBarTemplate })),
88
+ "progressRing": () => import("./chart-progress-ring-OR2VOIHV.js").then((module) => ({ default: module.ChartProgressRingTemplate })),
89
+ "phoneMockup": () => import("./showcase-phone-M4CEANIW.js").then((module) => ({ default: module.ShowcasePhoneTemplate })),
90
+ "webMockup": () => import("./showcase-web-TY6CZV2Z.js").then((module) => ({ default: module.ShowcaseWebTemplate })),
91
+ "codeEditor": () => import("./showcase-code-KHSMIPG6.js").then((module) => ({ default: module.ShowcaseCodeTemplate })),
92
+ "terminal": () => import("./showcase-terminal-26I3DYF7.js").then((module) => ({ default: module.ShowcaseTerminalTemplate })),
93
+ "tweet": () => import("./social-tweet-TK7SH2F6.js").then((module) => ({ default: module.SocialTweetTemplate })),
94
+ "notification": () => import("./social-notification-2RJDAZSF.js").then((module) => ({ default: module.SocialNotificationTemplate })),
95
95
  "chatMessenger": () => import("./social-conversation-75SD2637.js").then((module) => ({ default: module.SocialConversationTemplate })),
96
96
  "chatWhatsapp": () => import("./social-conversation-75SD2637.js").then((module) => ({ default: module.SocialConversationTemplate })),
97
- "milestone": () => import("./social-milestone-KPKHFOB5.js").then((module) => ({ default: module.SocialMilestoneTemplate })),
98
- "reviewStack": () => import("./social-review-stack-EZOO33SV.js").then((module) => ({ default: module.SocialReviewStackTemplate })),
99
- "testimonial": () => import("./social-testimonial-DLOINMMY.js").then((module) => ({ default: module.SocialTestimonialTemplate })),
100
- "incomingCall": () => import("./incoming-call-5IWJ2TAS.js").then((module) => ({ default: module.IncomingCallTemplate })),
101
- "brandMessage": () => import("./brand-message-P56WEJPG.js").then((module) => ({ default: module.BrandMessageTemplate })),
102
- "promptInput": () => import("./prompt-input-6ZWXEL3V.js").then((module) => ({ default: module.PromptInputTemplate })),
97
+ "milestone": () => import("./social-milestone-TF6MX7ET.js").then((module) => ({ default: module.SocialMilestoneTemplate })),
98
+ "reviewStack": () => import("./social-review-stack-2ICKJQG7.js").then((module) => ({ default: module.SocialReviewStackTemplate })),
99
+ "testimonial": () => import("./social-testimonial-X7OGADA3.js").then((module) => ({ default: module.SocialTestimonialTemplate })),
100
+ "incomingCall": () => import("./incoming-call-KXF67OT2.js").then((module) => ({ default: module.IncomingCallTemplate })),
101
+ "brandMessage": () => import("./brand-message-XHONEDNW.js").then((module) => ({ default: module.BrandMessageTemplate })),
102
+ "promptInput": () => import("./prompt-input-F3CYU2XH.js").then((module) => ({ default: module.PromptInputTemplate })),
103
103
  "beforeAfter": () => import("./infographic-before-after-2I7YZVDD.js").then((module) => ({ default: module.InfographicBeforeAfterTemplate })),
104
- "tripleStats": () => import("./infographic-stat-row-XHUZZPDM.js").then((module) => ({ default: module.InfographicStatRowTemplate })),
105
- "problemSolution": () => import("./infographic-problem-solution-IW35S6BR.js").then((module) => ({ default: module.InfographicProblemSolutionTemplate })),
106
- "cardList": () => import("./infographic-feature-list-7SK65U3K.js").then((module) => ({ default: module.InfographicFeatureListTemplate })),
107
- "steps": () => import("./infographic-steps-JDDEDI7X.js").then((module) => ({ default: module.InfographicStepsTemplate })),
108
- "ctaLogo": () => import("./cta-logo-S4OMTNXD.js").then((module) => ({ default: module.CtaLogoTemplate })),
109
- "ctaMedia": () => import("./cta-media-EROTHDRR.js").then((module) => ({ default: module.CtaMediaTemplate }))
104
+ "tripleStats": () => import("./infographic-stat-row-VFTIXS5F.js").then((module) => ({ default: module.InfographicStatRowTemplate })),
105
+ "problemSolution": () => import("./infographic-problem-solution-FMLJCPG6.js").then((module) => ({ default: module.InfographicProblemSolutionTemplate })),
106
+ "cardList": () => import("./infographic-feature-list-QDM4I7XE.js").then((module) => ({ default: module.InfographicFeatureListTemplate })),
107
+ "steps": () => import("./infographic-steps-L7W24Z35.js").then((module) => ({ default: module.InfographicStepsTemplate })),
108
+ "ctaLogo": () => import("./cta-logo-JJOGK4UC.js").then((module) => ({ default: module.CtaLogoTemplate })),
109
+ "ctaMedia": () => import("./cta-media-IQ3MAWEH.js").then((module) => ({ default: module.CtaMediaTemplate }))
110
110
  };
111
111
 
112
112
  // src/visual-system/catalog/builtin-player.generated.ts
@@ -1083,6 +1083,7 @@ function VideoPlayerRuntime({
1083
1083
  playbackMode,
1084
1084
  autoPlay = true,
1085
1085
  startMuted = true,
1086
+ nativeMediaAudio,
1086
1087
  width,
1087
1088
  orientation: orientationOverride,
1088
1089
  responsiveBreakpoint = 520,
@@ -1095,6 +1096,10 @@ function VideoPlayerRuntime({
1095
1096
  onSceneChange,
1096
1097
  onStateChange
1097
1098
  }) {
1099
+ const nativeMediaVolume = Math.max(0, Math.min(
1100
+ 1,
1101
+ typeof nativeMediaAudio?.volume === "number" && Number.isFinite(nativeMediaAudio.volume) ? nativeMediaAudio.volume : 1
1102
+ ));
1098
1103
  const [reducedMotion, setReducedMotion] = useState(
1099
1104
  () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
1100
1105
  );
@@ -1459,6 +1464,8 @@ function VideoPlayerRuntime({
1459
1464
  width: dimensions.width,
1460
1465
  height: dimensions.height,
1461
1466
  playing: isPlaying,
1467
+ mediaAudioMuted: !nativeMediaAudio || isMuted,
1468
+ mediaAudioVolume: nativeMediaVolume,
1462
1469
  style: {
1463
1470
  position: "absolute",
1464
1471
  left: 0,
@@ -1500,7 +1507,7 @@ function VideoPlayerRuntime({
1500
1507
  isPlaying,
1501
1508
  isMuted,
1502
1509
  isFullscreen,
1503
- hasAudio: Boolean(config?.audio),
1510
+ hasAudio: Boolean(config?.audio) || Boolean(nativeMediaAudio),
1504
1511
  onTogglePlayback: togglePlayback,
1505
1512
  onToggleMuted: () => setIsMuted((muted) => {
1506
1513
  if (muted) setAudioUnlocked(true);
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  SceneBackground
3
- } from "./chunk-6M6DATLW.js";
3
+ } from "./chunk-7BGAU6C3.js";
4
4
  import {
5
5
  TemplateText
6
6
  } from "./chunk-TCEHK2BW.js";
7
7
  import "./chunk-L5BTTCZV.js";
8
- import "./chunk-HT6BGERF.js";
8
+ import "./chunk-FRN6WKHA.js";
9
9
  import "./chunk-W3VDIBGR.js";
10
10
  import "./chunk-XTOXFMLM.js";
11
- import "./chunk-C6WVCZRW.js";
12
11
  import "./chunk-224QNWRA.js";
12
+ import "./chunk-5CDAM24P.js";
13
13
  import {
14
14
  resolveTokens
15
15
  } from "./chunk-XWWLKRNU.js";
@@ -1,8 +1,9 @@
1
1
  import {
2
2
  SceneVideoBackdrop
3
- } from "./chunk-HT6BGERF.js";
3
+ } from "./chunk-FRN6WKHA.js";
4
4
  import "./chunk-W3VDIBGR.js";
5
5
  import "./chunk-XTOXFMLM.js";
6
+ import "./chunk-5CDAM24P.js";
6
7
  import "./chunk-XWWLKRNU.js";
7
8
  export {
8
9
  SceneVideoBackdrop
package/dist/server.d.ts CHANGED
@@ -129,6 +129,8 @@ interface ResolvedMedia {
129
129
  }
130
130
  interface MediaResolverContext {
131
131
  input: VideoInput;
132
+ requestId: string;
133
+ scene: Readonly<VideoScene>;
132
134
  templateId: string;
133
135
  preferredType: "image" | "video" | "any";
134
136
  signal: AbortSignal;
package/dist/server.js CHANGED
@@ -476,6 +476,8 @@ async function resolveVariables(options) {
476
476
  try {
477
477
  resolved = await options.resolveMedia(rawQuery, {
478
478
  input: options.input,
479
+ requestId: options.requestId,
480
+ scene: { ...options.scene, variables },
479
481
  templateId: options.templateId,
480
482
  preferredType: preferredType(variables.mediaType),
481
483
  signal: options.signal
@@ -533,6 +535,8 @@ async function resolvePartVariables(options) {
533
535
  if (options.part.type === "scene.add") {
534
536
  const variables = await resolveVariables({
535
537
  ...shared,
538
+ requestId: options.requestId,
539
+ scene: options.part.scene,
536
540
  variables: options.part.scene.variables
537
541
  });
538
542
  return { ...options.part, scene: { ...options.part.scene, variables } };
@@ -544,6 +548,7 @@ function createMediaResolvingPlanner(options) {
544
548
  for await (const part of options.planner(context)) {
545
549
  yield await resolvePartVariables({
546
550
  part,
551
+ requestId: context.request.requestId,
547
552
  templateId: part.type === "scene.add" ? part.scene.templateId : void 0,
548
553
  input: context.request.input,
549
554
  signal: context.signal,
@@ -5,21 +5,21 @@ import {
5
5
  import {
6
6
  SceneBackground,
7
7
  getMediaBackgroundProps
8
- } from "./chunk-6M6DATLW.js";
8
+ } from "./chunk-7BGAU6C3.js";
9
9
  import {
10
10
  TemplateText
11
11
  } from "./chunk-TCEHK2BW.js";
12
12
  import "./chunk-L5BTTCZV.js";
13
- import "./chunk-HT6BGERF.js";
13
+ import "./chunk-FRN6WKHA.js";
14
14
  import "./chunk-W3VDIBGR.js";
15
15
  import {
16
16
  interpolate,
17
17
  spring
18
18
  } from "./chunk-XTOXFMLM.js";
19
- import "./chunk-C6WVCZRW.js";
20
19
  import {
21
20
  hasSceneMedia
22
21
  } from "./chunk-224QNWRA.js";
22
+ import "./chunk-5CDAM24P.js";
23
23
  import {
24
24
  resolveTokens
25
25
  } from "./chunk-XWWLKRNU.js";
@@ -7,22 +7,22 @@ import "./chunk-S7HFLYNN.js";
7
7
  import {
8
8
  SceneBackground,
9
9
  getMediaBackgroundProps
10
- } from "./chunk-6M6DATLW.js";
10
+ } from "./chunk-7BGAU6C3.js";
11
11
  import {
12
12
  TemplateText
13
13
  } from "./chunk-TCEHK2BW.js";
14
14
  import "./chunk-L5BTTCZV.js";
15
- import "./chunk-HT6BGERF.js";
15
+ import "./chunk-FRN6WKHA.js";
16
16
  import "./chunk-W3VDIBGR.js";
17
17
  import {
18
18
  SPRING_SMOOTH,
19
19
  interpolate,
20
20
  spring
21
21
  } from "./chunk-XTOXFMLM.js";
22
- import "./chunk-C6WVCZRW.js";
23
22
  import {
24
23
  hasSceneMedia
25
24
  } from "./chunk-224QNWRA.js";
25
+ import "./chunk-5CDAM24P.js";
26
26
  import {
27
27
  TOKEN_DEFAULTS,
28
28
  resolveTokens
@@ -7,21 +7,21 @@ import {
7
7
  import {
8
8
  SceneBackground,
9
9
  getMediaBackgroundProps
10
- } from "./chunk-6M6DATLW.js";
10
+ } from "./chunk-7BGAU6C3.js";
11
11
  import {
12
12
  TemplateText
13
13
  } from "./chunk-TCEHK2BW.js";
14
14
  import "./chunk-L5BTTCZV.js";
15
- import "./chunk-HT6BGERF.js";
15
+ import "./chunk-FRN6WKHA.js";
16
16
  import "./chunk-W3VDIBGR.js";
17
17
  import {
18
18
  interpolate,
19
19
  spring
20
20
  } from "./chunk-XTOXFMLM.js";
21
- import "./chunk-C6WVCZRW.js";
22
21
  import {
23
22
  hasSceneMedia
24
23
  } from "./chunk-224QNWRA.js";
24
+ import "./chunk-5CDAM24P.js";
25
25
  import {
26
26
  TOKEN_DEFAULTS,
27
27
  resolveTokens
@@ -9,22 +9,22 @@ import {
9
9
  import {
10
10
  SceneBackground,
11
11
  getMediaBackgroundProps
12
- } from "./chunk-6M6DATLW.js";
12
+ } from "./chunk-7BGAU6C3.js";
13
13
  import {
14
14
  TemplateText
15
15
  } from "./chunk-TCEHK2BW.js";
16
16
  import "./chunk-L5BTTCZV.js";
17
- import "./chunk-HT6BGERF.js";
17
+ import "./chunk-FRN6WKHA.js";
18
18
  import "./chunk-W3VDIBGR.js";
19
19
  import {
20
20
  SPRING_SMOOTH,
21
21
  interpolate,
22
22
  spring
23
23
  } from "./chunk-XTOXFMLM.js";
24
- import "./chunk-C6WVCZRW.js";
25
24
  import {
26
25
  hasSceneMedia
27
26
  } from "./chunk-224QNWRA.js";
27
+ import "./chunk-5CDAM24P.js";
28
28
  import {
29
29
  TOKEN_DEFAULTS,
30
30
  resolveTokens
@@ -8,12 +8,12 @@ import "./chunk-QAAO7OAY.js";
8
8
  import {
9
9
  SceneBackground,
10
10
  getMediaBackgroundProps
11
- } from "./chunk-6M6DATLW.js";
11
+ } from "./chunk-7BGAU6C3.js";
12
12
  import {
13
13
  Emoji,
14
14
  renderWithEmoji
15
15
  } from "./chunk-L5BTTCZV.js";
16
- import "./chunk-HT6BGERF.js";
16
+ import "./chunk-FRN6WKHA.js";
17
17
  import {
18
18
  accessibleTextColor,
19
19
  withOpacity
@@ -24,8 +24,8 @@ import {
24
24
  interpolate,
25
25
  spring
26
26
  } from "./chunk-XTOXFMLM.js";
27
- import "./chunk-C6WVCZRW.js";
28
27
  import "./chunk-224QNWRA.js";
28
+ import "./chunk-5CDAM24P.js";
29
29
  import {
30
30
  MEDIA_TEXT_SHADOW,
31
31
  TOKEN_DEFAULTS,
@@ -4,20 +4,20 @@ import {
4
4
  import {
5
5
  SceneBackground,
6
6
  getMediaBackgroundProps
7
- } from "./chunk-6M6DATLW.js";
7
+ } from "./chunk-7BGAU6C3.js";
8
8
  import {
9
9
  Emoji,
10
10
  renderWithEmoji
11
11
  } from "./chunk-L5BTTCZV.js";
12
- import "./chunk-HT6BGERF.js";
12
+ import "./chunk-FRN6WKHA.js";
13
13
  import "./chunk-W3VDIBGR.js";
14
14
  import {
15
15
  SPRING_SMOOTH,
16
16
  interpolate,
17
17
  spring
18
18
  } from "./chunk-XTOXFMLM.js";
19
- import "./chunk-C6WVCZRW.js";
20
19
  import "./chunk-224QNWRA.js";
20
+ import "./chunk-5CDAM24P.js";
21
21
  import {
22
22
  resolveTokens
23
23
  } from "./chunk-XWWLKRNU.js";
@@ -4,8 +4,8 @@ import {
4
4
  import {
5
5
  SceneBackground,
6
6
  getMediaBackgroundProps
7
- } from "./chunk-6M6DATLW.js";
8
- import "./chunk-HT6BGERF.js";
7
+ } from "./chunk-7BGAU6C3.js";
8
+ import "./chunk-FRN6WKHA.js";
9
9
  import {
10
10
  accessibleTextColor,
11
11
  withOpacity
@@ -15,8 +15,8 @@ import {
15
15
  interpolate,
16
16
  spring
17
17
  } from "./chunk-XTOXFMLM.js";
18
- import "./chunk-C6WVCZRW.js";
19
18
  import "./chunk-224QNWRA.js";
19
+ import "./chunk-5CDAM24P.js";
20
20
  import {
21
21
  lighten,
22
22
  resolveTokens
@@ -4,8 +4,8 @@ import {
4
4
  import {
5
5
  SceneBackground,
6
6
  getMediaBackgroundProps
7
- } from "./chunk-6M6DATLW.js";
8
- import "./chunk-HT6BGERF.js";
7
+ } from "./chunk-7BGAU6C3.js";
8
+ import "./chunk-FRN6WKHA.js";
9
9
  import {
10
10
  accessibleTextColor,
11
11
  autoTextColor,
@@ -17,8 +17,8 @@ import {
17
17
  interpolate,
18
18
  spring
19
19
  } from "./chunk-XTOXFMLM.js";
20
- import "./chunk-C6WVCZRW.js";
21
20
  import "./chunk-224QNWRA.js";
21
+ import "./chunk-5CDAM24P.js";
22
22
  import {
23
23
  TOKEN_DEFAULTS,
24
24
  lighten,
@@ -4,11 +4,11 @@ import {
4
4
  import {
5
5
  SceneBackground,
6
6
  getMediaBackgroundProps
7
- } from "./chunk-6M6DATLW.js";
7
+ } from "./chunk-7BGAU6C3.js";
8
8
  import {
9
9
  renderWithEmoji
10
10
  } from "./chunk-L5BTTCZV.js";
11
- import "./chunk-HT6BGERF.js";
11
+ import "./chunk-FRN6WKHA.js";
12
12
  import {
13
13
  autoTextColor
14
14
  } from "./chunk-W3VDIBGR.js";
@@ -17,8 +17,8 @@ import {
17
17
  interpolate,
18
18
  spring
19
19
  } from "./chunk-XTOXFMLM.js";
20
- import "./chunk-C6WVCZRW.js";
21
20
  import "./chunk-224QNWRA.js";
21
+ import "./chunk-5CDAM24P.js";
22
22
  import {
23
23
  resolveTokens
24
24
  } from "./chunk-XWWLKRNU.js";
@@ -94,6 +94,65 @@ timeline wraps. This does not bypass browser autoplay policy: use muted autoplay
94
94
  for unattended playback and let a viewer unmute, or start audible playback from
95
95
  a user interaction.
96
96
 
97
+ ## Mix native clip audio with a soundtrack
98
+
99
+ Some generated or supplied scene videos contain their own synchronized
100
+ dialogue, effects, or ambience. Opt into that embedded track at the player:
101
+
102
+ ```tsx
103
+ <VideoPlayer
104
+ video={video}
105
+ nativeMediaAudio={{ volume: 0.85 }}
106
+ playbackMode="muted-autoplay"
107
+ />
108
+ ```
109
+
110
+ This produces two independent layers: the active scene video's native audio
111
+ at `nativeMediaAudio.volume`, and the continuous soundtrack at the serialized
112
+ `video.audio.volume`. The existing sound button is their shared master mute.
113
+ Incoming videos may preroll visually, but remain muted until their scene is
114
+ active. Native media audio is off by default so existing players keep their
115
+ current soundtrack-only behavior.
116
+
117
+ ## Generate media instead of searching for it
118
+
119
+ `resolveMedia` does not have to search a catalog. The same callback can
120
+ generate the asset, because it receives the `requestId` and the `scene` being
121
+ resolved alongside the query:
122
+
123
+ ```ts
124
+ resolveMedia: async (query, { requestId, scene, preferredType, signal }) => {
125
+ const asset = await generateAndStore({ prompt: query, requestId, scene, preferredType, signal });
126
+ return asset ? { url: asset.url, type: asset.type } : null;
127
+ }
128
+ ```
129
+
130
+ Generation stays outside the SDK install. VanillaSky depends on no image or
131
+ video model, and never selects a provider: the application supplies the model
132
+ and owns the key, the spend, and where bytes are stored.
133
+
134
+ [`examples/server-integrations/src/ai-sdk-media.ts`](../examples/server-integrations/src/ai-sdk-media.ts)
135
+ is a provider-neutral adapter built on the AI SDK. It takes `ImageModel` and
136
+ `VideoModel` instances rather than naming a vendor, so it runs against any
137
+ model the AI SDK supports. Install the AI SDK and whichever provider you
138
+ chose — for example:
139
+
140
+ ```bash
141
+ npm install ai @ai-sdk/fal
142
+ ```
143
+
144
+ Two rules that example encodes, both about money:
145
+
146
+ - **`maxRetries: 0`.** A generated asset is billable, so a silent retry can
147
+ charge twice for one scene. Retrying stays an explicit, budget-aware
148
+ decision in the application.
149
+ - **A per-scene idempotency key** built from `requestId` and `scene.id`, so a
150
+ retried request reuses the stored object instead of generating a second one.
151
+
152
+ Generation is slower than a catalog lookup. Honour `signal`, keep a deadline,
153
+ and return `null` when it passes: a scene that falls back to the brand
154
+ gradient is better than one that never arrives.
155
+
97
156
  ## Media providers
98
157
 
99
158
  VanillaSky is provider-independent. When `resolveMedia` is configured, the
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "dependencies": {
11
11
  "@ai-sdk/anthropic": "^4.0.41",
12
- "@vanillaskyai/video": "0.5.8",
12
+ "@vanillaskyai/video": "0.6.0",
13
13
  "ai": "^7.0.77",
14
14
  "next": "16.3.2",
15
15
  "react": "19.2.8",
@@ -2,9 +2,18 @@ import { anthropic } from "@ai-sdk/anthropic";
2
2
  import { streamText } from "ai";
3
3
  import { createVideoHandler } from "@vanillaskyai/video/server";
4
4
 
5
- const modelId = process.env.ANTHROPIC_MODEL;
6
- if (!modelId) throw new Error("Set ANTHROPIC_MODEL in the server environment");
7
- const model = anthropic(modelId);
5
+ // Resolved per request so the app still builds with the shipped placeholder.
6
+ function resolveModel() {
7
+ const modelId = process.env.ANTHROPIC_MODEL;
8
+ if (!modelId || modelId === "replace-with-current-sonnet-model") {
9
+ throw new Error(
10
+ "Set ANTHROPIC_MODEL in .env.local to a current Claude Sonnet model ID available to your " +
11
+ "account. The shipped value is a placeholder: VanillaSky never selects a provider or " +
12
+ "model for you.",
13
+ );
14
+ }
15
+ return anthropic(modelId);
16
+ }
8
17
 
9
18
  const handle = createVideoHandler({
10
19
  authorize: (request) => {
@@ -13,7 +22,7 @@ const handle = createVideoHandler({
13
22
  return hostname === "localhost" || hostname === "127.0.0.1";
14
23
  },
15
24
  streamText: ({ systemPrompt, userPrompt, signal }) => streamText({
16
- model,
25
+ model: resolveModel(),
17
26
  system: systemPrompt,
18
27
  prompt: userPrompt,
19
28
  abortSignal: signal,
@@ -0,0 +1,20 @@
1
+ # Server examples
2
+
3
+ The normal example uses the AI SDK's `streamText`, so any AI SDK `LanguageModel`
4
+ works without VanillaSky owning the provider, model, or credentials. Replace
5
+ `openai(modelId)` in `src/ai-sdk.ts` with an official provider, community
6
+ provider, AI Gateway model, OpenAI-compatible provider, or custom model.
7
+
8
+ `src/provider-neutral.ts` and `src/openai.ts` show the lower-level text-delta
9
+ escape hatch for applications that need to own the native provider loop.
10
+
11
+ <!-- verify:start -->
12
+ ```bash
13
+ npm install
14
+ npm run typecheck
15
+ npm run ai-sdk:compat
16
+ ```
17
+ <!-- verify:end -->
18
+
19
+ Use the returned Web `Request` → `Response` handler directly in Next.js, Hono,
20
+ Remix, Cloudflare Workers, or another standards-based server runtime.