@vanillaskyai/video 0.6.0 → 0.7.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.
- package/CHANGELOG.md +164 -0
- package/PUBLIC-API.md +123 -9
- package/README.md +69 -115
- 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-G4XOQEAS.js → bg-media-L34PDQXJ.js} +2 -2
- package/dist/{brand-message-XHONEDNW.js → brand-message-FUJ4STFO.js} +1 -1
- package/dist/{builtin-server-YHEZ2JRF.js → builtin-server-KB7FKF6A.js} +2 -2
- package/dist/{chart-bar-HRHD57ML.js → chart-bar-EGPHJATL.js} +2 -2
- package/dist/{chart-counter-KFPV44RB.js → chart-counter-5FFWQNZO.js} +2 -2
- package/dist/{chart-progress-ring-OR2VOIHV.js → chart-progress-ring-JMXQLMLC.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-PNS52FL4.js → chunk-5SLENAJW.js} +19 -6
- package/dist/{chunk-EFL34TXF.js → chunk-AITKH6QT.js} +24 -8
- package/dist/{chunk-FZHMQFG3.js → chunk-GAIOHGNR.js} +5 -21
- package/dist/{chunk-3RV4YKB3.js → chunk-JNN3EYVP.js} +51 -26
- package/dist/{chunk-HVCPEAQF.js → chunk-LKBZX7GV.js} +9 -6
- package/dist/{chunk-34O5BY6X.js → chunk-LLPMVDJZ.js} +21 -4
- package/dist/{chunk-G66Z5CWR.js → chunk-MMUXVA47.js} +27 -3
- package/dist/{chunk-7BGAU6C3.js → chunk-MXZSDGZQ.js} +2 -1
- package/dist/{chunk-3OU7HIEB.js → chunk-RE4IMWJR.js} +15 -31
- package/dist/{chunk-FVTMYS6U.js → chunk-RGF452LL.js} +1 -1
- 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-JJOGK4UC.js → cta-logo-YR7LYUR5.js} +1 -1
- package/dist/{cta-media-IQ3MAWEH.js → cta-media-DQJBKUO2.js} +2 -2
- package/dist/{events-BBP30j3c.d.ts → events-B6qS1Lsb.d.ts} +2 -2
- package/dist/{incoming-call-KXF67OT2.js → incoming-call-54KQ7O5A.js} +1 -1
- 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-QDM4I7XE.js → infographic-feature-list-E7MGUDAN.js} +2 -2
- package/dist/{infographic-problem-solution-FMLJCPG6.js → infographic-problem-solution-3S6NGO5N.js} +2 -2
- package/dist/{infographic-stat-row-VFTIXS5F.js → infographic-stat-row-SYB7AB7H.js} +2 -2
- package/dist/{infographic-steps-L7W24Z35.js → infographic-steps-KCE6JWE2.js} +2 -2
- package/dist/{kit-DEG3fcaL.d.ts → kit-8g46H2RZ.d.ts} +1 -1
- package/dist/{prompt-input-F3CYU2XH.js → prompt-input-MHX4O42G.js} +1 -1
- package/dist/react.d.ts +194 -6
- package/dist/react.js +1849 -40
- package/dist/{reaction-2XCLOJOK.js → reaction-SLEGR3BE.js} +2 -2
- package/dist/server.d.ts +102 -4
- package/dist/server.js +972 -27
- package/dist/{showcase-code-KHSMIPG6.js → showcase-code-2HLAVKBM.js} +2 -2
- package/dist/{showcase-phone-M4CEANIW.js → showcase-phone-Q4HEO4LH.js} +2 -2
- package/dist/{showcase-terminal-26I3DYF7.js → showcase-terminal-DL45LUFG.js} +2 -2
- package/dist/{showcase-web-TY6CZV2Z.js → showcase-web-2QZO73FZ.js} +2 -2
- package/dist/{social-milestone-TF6MX7ET.js → social-milestone-GEFUQSBF.js} +1 -1
- package/dist/{social-notification-2RJDAZSF.js → social-notification-FJ5VHVLK.js} +1 -1
- package/dist/{social-review-stack-2ICKJQG7.js → social-review-stack-KXQCKFRP.js} +1 -1
- package/dist/{social-testimonial-X7OGADA3.js → social-testimonial-JZ7CHC7S.js} +1 -1
- package/dist/{social-tweet-TK7SH2F6.js → social-tweet-UCDXM25F.js} +1 -1
- 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-ROTNGSD4.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 +103 -166
- 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 -22
- 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/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 -33
- 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/examples/server-integrations/README.md +0 -20
- package/examples/server-integrations/src/ai-sdk-media.ts +0 -90
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { c as Video,
|
|
2
|
-
export {
|
|
1
|
+
import { c as Video, h as VideoBrandInput, i as VideoBrand, e as VideoScene, d as VideoAudio, V as VideoStyle, b as VideoOrientation, j as VideoTemplatePacing } from './types-2wHBqtg8.js';
|
|
2
|
+
export { k as VideoBackground, g as VideoInput, l as VideoKnowledgeMode, m as VideoStyleOptions, n as VideoSuppliedMedia } from './types-2wHBqtg8.js';
|
|
3
3
|
export { V as VideoStatus } from './state-DZcKuS32.js';
|
|
4
|
+
import { b as VideoEvent } from './events-B6qS1Lsb.js';
|
|
4
5
|
|
|
5
6
|
type VideoValidationErrorCode = "invalid_video" | "unsupported_video_version";
|
|
6
7
|
declare class VideoValidationError extends Error {
|
|
@@ -14,4 +15,89 @@ declare function getVideoDuration(config: Video): number;
|
|
|
14
15
|
|
|
15
16
|
declare function resolveVideoBrand(input?: VideoBrandInput): VideoBrand;
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Compose a playable video from scenes the host builds itself.
|
|
20
|
+
*
|
|
21
|
+
* `VideoInput.opening` is a single line of copy, so an application that wants
|
|
22
|
+
* several scenes of its own before the generated ones has nowhere to put them.
|
|
23
|
+
* Handing the player a fresh `video` prop is not an answer either: that resets
|
|
24
|
+
* playback to zero on every change, so a video that grows replays its opening
|
|
25
|
+
* each time something is appended. The player's `stream` prop appends, and this
|
|
26
|
+
* builds a stream.
|
|
27
|
+
*
|
|
28
|
+
* The reason it belongs here rather than in each application is that the
|
|
29
|
+
* envelope rules are exact and their failure is silent. `response.start` must
|
|
30
|
+
* be sequence zero, every event exactly one higher, `eventId` exactly
|
|
31
|
+
* `${runId}:${sequence}`, `scene.add.position` the index the scene lands at,
|
|
32
|
+
* and the completion snapshot must reproduce what the reducer built. Miss any
|
|
33
|
+
* one and the whole stream is rejected: the player renders nothing, and the
|
|
34
|
+
* console stays clean.
|
|
35
|
+
*/
|
|
36
|
+
interface SceneTimeline {
|
|
37
|
+
/**
|
|
38
|
+
* Hand this to the player's `stream` prop once. Never swap it: a new stream
|
|
39
|
+
* is a new video, and playback restarts.
|
|
40
|
+
*/
|
|
41
|
+
stream: AsyncIterable<VideoEvent>;
|
|
42
|
+
/** Append a scene. Ignored once the timeline has completed. */
|
|
43
|
+
add(scene: VideoScene): void;
|
|
44
|
+
/**
|
|
45
|
+
* Say what the soundtrack is, or that there is none.
|
|
46
|
+
*
|
|
47
|
+
* Only meaningful with `awaitAudio`, where it releases the scenes held back
|
|
48
|
+
* while the track was unknown. Calling it twice, or after the first scene has
|
|
49
|
+
* been emitted, does nothing.
|
|
50
|
+
*/
|
|
51
|
+
setAudio(audio: VideoAudio | undefined): void;
|
|
52
|
+
/** Finish the video. Safe to call more than once. */
|
|
53
|
+
complete(): void;
|
|
54
|
+
}
|
|
55
|
+
interface SceneTimelineOptions {
|
|
56
|
+
style: VideoStyle;
|
|
57
|
+
orientation?: VideoOrientation;
|
|
58
|
+
/**
|
|
59
|
+
* The soundtrack, when it is already known.
|
|
60
|
+
*
|
|
61
|
+
* Use `awaitAudio` instead when it is resolved by a request that has not
|
|
62
|
+
* answered yet.
|
|
63
|
+
*/
|
|
64
|
+
audio?: VideoAudio;
|
|
65
|
+
/**
|
|
66
|
+
* Hold scenes until `setAudio` is called.
|
|
67
|
+
*
|
|
68
|
+
* `audio.set` is only valid before the first scene, so a timeline that opens
|
|
69
|
+
* with host-built scenes cannot add a soundtrack afterwards - the event
|
|
70
|
+
* arrives too late and the video plays silently, with nothing to show for it.
|
|
71
|
+
* Holding the openings costs the wait for the track to resolve, not the wait
|
|
72
|
+
* for the video to be planned.
|
|
73
|
+
*/
|
|
74
|
+
awaitAudio?: boolean;
|
|
75
|
+
requestId?: string;
|
|
76
|
+
runId?: string;
|
|
77
|
+
}
|
|
78
|
+
declare function createSceneTimeline(options: SceneTimelineOptions): SceneTimeline;
|
|
79
|
+
|
|
80
|
+
interface SceneDurationBounds {
|
|
81
|
+
/**
|
|
82
|
+
* The least this scene survives being shown for.
|
|
83
|
+
*
|
|
84
|
+
* A compression bound, used when a video must fit a fixed length. It is not
|
|
85
|
+
* a readability bound and should not be used as one.
|
|
86
|
+
*/
|
|
87
|
+
minimum: number;
|
|
88
|
+
/** How long the scene's own content takes to read, given what it holds. */
|
|
89
|
+
readable: number;
|
|
90
|
+
}
|
|
91
|
+
declare function getSceneDurationBounds(scene: Pick<VideoScene, "variables">, metadata: VideoTemplatePacing | undefined): SceneDurationBounds;
|
|
92
|
+
/**
|
|
93
|
+
* How long a narrated line takes to say.
|
|
94
|
+
*
|
|
95
|
+
* Reading is faster than speech - the readable estimate runs at 4.5 words a
|
|
96
|
+
* second, a realtime voice lands nearer 2.6 - so the two bounds measure
|
|
97
|
+
* different things and a scene needs whichever is longer. The tail covers the
|
|
98
|
+
* breath between lines.
|
|
99
|
+
*/
|
|
100
|
+
declare function getSpokenDuration(narration: string): number;
|
|
101
|
+
declare function getSceneDuration(scene: Pick<VideoScene, "variables" | "narration">, metadata: VideoTemplatePacing | undefined): number;
|
|
102
|
+
|
|
103
|
+
export { type SceneDurationBounds, type SceneTimeline, type SceneTimelineOptions, Video, VideoAudio, VideoBrand, VideoBrandInput, VideoOrientation, VideoScene, VideoStyle, VideoValidationError, type VideoValidationErrorCode, createSceneTimeline, getSceneDuration, getSceneDurationBounds, getSpokenDuration, getVideoDuration, parseVideo, resolveVideoBrand };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createSceneTimeline,
|
|
3
|
+
getSceneDuration,
|
|
4
|
+
getSceneDurationBounds,
|
|
5
|
+
getSpokenDuration
|
|
6
|
+
} from "./chunk-SKRGRKHY.js";
|
|
1
7
|
import {
|
|
2
8
|
VideoValidationError,
|
|
3
9
|
parseVideo
|
|
4
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-2PYO6VAC.js";
|
|
5
11
|
import "./chunk-AOWSXU2K.js";
|
|
12
|
+
import "./chunk-3O7OMMMF.js";
|
|
6
13
|
import {
|
|
7
14
|
getVideoDuration
|
|
8
15
|
} from "./chunk-SPVTJH3F.js";
|
|
@@ -11,6 +18,10 @@ import {
|
|
|
11
18
|
} from "./chunk-XGRA2MUV.js";
|
|
12
19
|
export {
|
|
13
20
|
VideoValidationError,
|
|
21
|
+
createSceneTimeline,
|
|
22
|
+
getSceneDuration,
|
|
23
|
+
getSceneDurationBounds,
|
|
24
|
+
getSpokenDuration,
|
|
14
25
|
getVideoDuration,
|
|
15
26
|
parseVideo,
|
|
16
27
|
resolveVideoBrand
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
SceneBackground,
|
|
9
9
|
getMediaBackgroundProps
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-MXZSDGZQ.js";
|
|
11
11
|
import {
|
|
12
12
|
TemplateText
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-YJJC4N4D.js";
|
|
14
14
|
import {
|
|
15
15
|
Emoji
|
|
16
16
|
} from "./chunk-L5BTTCZV.js";
|
package/dist/{infographic-problem-solution-FMLJCPG6.js → infographic-problem-solution-3S6NGO5N.js}
RENAMED
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
SceneBackground,
|
|
6
6
|
getMediaBackgroundProps
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-MXZSDGZQ.js";
|
|
8
8
|
import {
|
|
9
9
|
smoothSize
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-YJJC4N4D.js";
|
|
11
11
|
import "./chunk-L5BTTCZV.js";
|
|
12
12
|
import "./chunk-FRN6WKHA.js";
|
|
13
13
|
import "./chunk-W3VDIBGR.js";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SceneBackground,
|
|
3
3
|
getMediaBackgroundProps
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-MXZSDGZQ.js";
|
|
5
5
|
import {
|
|
6
6
|
TemplateText
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YJJC4N4D.js";
|
|
8
8
|
import "./chunk-L5BTTCZV.js";
|
|
9
9
|
import "./chunk-FRN6WKHA.js";
|
|
10
10
|
import {
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
SceneBackground,
|
|
10
10
|
getMediaBackgroundProps
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-MXZSDGZQ.js";
|
|
12
12
|
import {
|
|
13
13
|
TemplateText
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-YJJC4N4D.js";
|
|
15
15
|
import {
|
|
16
16
|
Emoji
|
|
17
17
|
} from "./chunk-L5BTTCZV.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { V as VideoStyle, a as VideoCapabilities } from './types-
|
|
1
|
+
import { V as VideoStyle, a as VideoCapabilities } from './types-2wHBqtg8.js';
|
|
2
2
|
import { ComponentType } from 'react';
|
|
3
3
|
import { S as SceneTemplateMetadata, d as TemplateJsonSchema, f as TemplateJsonSchemaProperty } from './catalog-types-BIhSpOWK.js';
|
|
4
4
|
|
package/dist/react.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { b as
|
|
4
|
-
import {
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { CSSProperties, ReactElement, ReactNode } from 'react';
|
|
3
|
+
import { b as VideoEvent, V as VideoWarning } from './events-B6qS1Lsb.js';
|
|
4
|
+
import { b as VideoOrientation, c as Video, e as VideoScene, g as VideoInput, h as VideoBrandInput, m as VideoStyleOptions } from './types-2wHBqtg8.js';
|
|
5
|
+
import { T as TemplateRegistry } from './kit-8g46H2RZ.js';
|
|
5
6
|
import { V as VideoStatus } from './state-DZcKuS32.js';
|
|
7
|
+
import { c as VideoChatMode, e as VideoChatAskOptions, f as VideoChatMedia, g as VideoChatSuggestion, a as VideoChatCapabilities, h as VideoChatWelcome } from './types-DrABlRa7.js';
|
|
6
8
|
import './catalog-types-BIhSpOWK.js';
|
|
7
9
|
|
|
8
10
|
type VideoPlaybackMode = "manual" | "muted-autoplay" | "autoplay-with-sound" | "autoplay-after-interaction";
|
|
@@ -29,8 +31,35 @@ interface VideoPlayerSharedProps {
|
|
|
29
31
|
style?: CSSProperties;
|
|
30
32
|
/** Accessible name for the player region. */
|
|
31
33
|
ariaLabel?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Show the player's own controls: play, mute, fullscreen, and the replay
|
|
36
|
+
* offered when the video ends. Default true.
|
|
37
|
+
*
|
|
38
|
+
* Turn them off where the host drives playback itself and a second set of
|
|
39
|
+
* controls would contradict it - a narrated answer whose voice and picture
|
|
40
|
+
* are one thing, where pausing the picture alone desynchronises them, and
|
|
41
|
+
* where a replay scrim would cover the answer the moment it finished.
|
|
42
|
+
*/
|
|
43
|
+
controls?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Hold the playhead where it is, and release it again.
|
|
46
|
+
*
|
|
47
|
+
* The counterpart to turning `controls` off. A host that owns playback needs
|
|
48
|
+
* a lever to drive it with, and until this there was none: the clock is the
|
|
49
|
+
* player's, so a narrated answer could silence its voice but not stop its
|
|
50
|
+
* picture, and the two came apart. Setting it back to false resumes from the
|
|
51
|
+
* same playhead rather than restarting.
|
|
52
|
+
*
|
|
53
|
+
* Leave it undefined to keep the player's own behaviour untouched. A video
|
|
54
|
+
* that has already reached its end is not resumed by it - the playhead is
|
|
55
|
+
* already there, and starting again is a replay, which is a different act.
|
|
56
|
+
*/
|
|
57
|
+
paused?: boolean;
|
|
32
58
|
/** Repeat the saved video and its soundtrack instead of showing the replay affordance. */
|
|
33
59
|
loop?: boolean;
|
|
60
|
+
/** Fires once when the playhead reaches the end of a non-looping video. */
|
|
61
|
+
onPlaybackEnd?: (video: Video) => void;
|
|
62
|
+
/** Fires when a streamed response has finished composing. */
|
|
34
63
|
onComplete?: (video: Video) => void;
|
|
35
64
|
onError?: (error: Error) => void;
|
|
36
65
|
/** Fires when the scene under the playhead changes, including on a loop wrap. */
|
|
@@ -46,7 +75,7 @@ type VideoPlayerProps = VideoPlayerSharedProps & ({
|
|
|
46
75
|
templates?: TemplateRegistry;
|
|
47
76
|
});
|
|
48
77
|
|
|
49
|
-
declare function VideoPlayer({ templates, stream, video, onComplete, onError, ...props }: VideoPlayerProps): ReactElement | null;
|
|
78
|
+
declare function VideoPlayer({ templates, stream, video, onPlaybackEnd, onComplete, onError, ...props }: VideoPlayerProps): ReactElement | null;
|
|
50
79
|
|
|
51
80
|
interface VideoErrorOptions {
|
|
52
81
|
code: string;
|
|
@@ -92,4 +121,163 @@ interface UseVideoResult {
|
|
|
92
121
|
}
|
|
93
122
|
declare function useVideo(options?: UseVideoOptions): UseVideoResult;
|
|
94
123
|
|
|
95
|
-
|
|
124
|
+
/**
|
|
125
|
+
* Say a video's narration as it plays.
|
|
126
|
+
*
|
|
127
|
+
* A narrated video is not a video with audio bolted on. The line belongs to the
|
|
128
|
+
* scene, so it has to begin when that scene does and stop when the viewer moves
|
|
129
|
+
* on - and every one of those was a bug in the application this was extracted
|
|
130
|
+
* from: the voice starting before the first frame, a follow-up question
|
|
131
|
+
* silently cutting the response off mid-sentence, a line still playing over the
|
|
132
|
+
* scene after it.
|
|
133
|
+
*
|
|
134
|
+
* The provider is not the SDK's business. An application supplies something
|
|
135
|
+
* that can speak - a realtime session, a speech model, the browser's own
|
|
136
|
+
* synthesiser - and this decides what is said, when it starts, and when it
|
|
137
|
+
* stops. That keeps the package free of provider dependencies and leaves the
|
|
138
|
+
* choice of voice where the choice of model already is.
|
|
139
|
+
*/
|
|
140
|
+
interface NarrationVoice {
|
|
141
|
+
/**
|
|
142
|
+
* Say this line, and resolve when it has been said.
|
|
143
|
+
*
|
|
144
|
+
* The signal aborts when the scene changes, when the viewer interrupts, or
|
|
145
|
+
* when the player goes away. Stop speaking promptly: talking over the next
|
|
146
|
+
* scene is worse than being cut off.
|
|
147
|
+
*/
|
|
148
|
+
speak(text: string, options: {
|
|
149
|
+
signal: AbortSignal;
|
|
150
|
+
}): void | Promise<void>;
|
|
151
|
+
}
|
|
152
|
+
interface NarrationOptions {
|
|
153
|
+
voice: NarrationVoice;
|
|
154
|
+
/** Say nothing at all while false. Defaults to true. */
|
|
155
|
+
enabled?: boolean;
|
|
156
|
+
}
|
|
157
|
+
interface Narration {
|
|
158
|
+
/**
|
|
159
|
+
* Hand this to the player's `onSceneChange`.
|
|
160
|
+
*
|
|
161
|
+
* The player already reports which scene is showing, which is the only cue a
|
|
162
|
+
* narrator needs, so nothing here has to run its own clock.
|
|
163
|
+
*/
|
|
164
|
+
onSceneChange: (scene: VideoScene, index: number) => void;
|
|
165
|
+
/** Stop the current line. Nothing is said again until the next scene. */
|
|
166
|
+
interrupt: () => void;
|
|
167
|
+
/** Whether a line is being spoken right now. */
|
|
168
|
+
speaking: boolean;
|
|
169
|
+
}
|
|
170
|
+
declare function useNarration(options: NarrationOptions): Narration;
|
|
171
|
+
|
|
172
|
+
interface VideoChatPreparedSpeech {
|
|
173
|
+
/** Measured or conservatively estimated spoken duration, in seconds. */
|
|
174
|
+
seconds: number;
|
|
175
|
+
}
|
|
176
|
+
interface VideoChatVoice extends NarrationVoice {
|
|
177
|
+
prepare(text: string, options?: {
|
|
178
|
+
signal?: AbortSignal;
|
|
179
|
+
}): Promise<VideoChatPreparedSpeech>;
|
|
180
|
+
pause(): void;
|
|
181
|
+
resume(): void;
|
|
182
|
+
setMuted(muted: boolean): void;
|
|
183
|
+
dispose?(): void;
|
|
184
|
+
}
|
|
185
|
+
interface CreateVideoChatVoiceOptions {
|
|
186
|
+
endpoint?: string | URL;
|
|
187
|
+
headers?: HeadersInit;
|
|
188
|
+
credentials?: RequestCredentials;
|
|
189
|
+
fetcher?: typeof fetch;
|
|
190
|
+
maxCachedLines?: number;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Create the SDK's generated-speech client with a browser-voice fallback.
|
|
194
|
+
*
|
|
195
|
+
* The endpoint is provider-neutral. A no-content response (or a compatible
|
|
196
|
+
* endpoint's 404) selects browser speech for the rest of the session.
|
|
197
|
+
*/
|
|
198
|
+
declare function createVideoChatVoice(options?: CreateVideoChatVoiceOptions): VideoChatVoice;
|
|
199
|
+
|
|
200
|
+
type VideoChatStatus = "idle" | "composing" | "playing" | "paused" | "ended" | "cancelled" | "error";
|
|
201
|
+
interface VideoChatTurn {
|
|
202
|
+
id: string;
|
|
203
|
+
prompt: string;
|
|
204
|
+
/** True only after the complete response has been received. */
|
|
205
|
+
completed: boolean;
|
|
206
|
+
opening?: string;
|
|
207
|
+
/** Optional stock footage held behind the opening hook until playback starts. */
|
|
208
|
+
openingMedia?: VideoChatMedia;
|
|
209
|
+
orientation: VideoOrientation;
|
|
210
|
+
/** Generated footage keeps the orientation it was created in. */
|
|
211
|
+
fixedOrientation: boolean;
|
|
212
|
+
video?: Video;
|
|
213
|
+
suggestions: readonly VideoChatSuggestion[];
|
|
214
|
+
}
|
|
215
|
+
interface UseVideoChatOptions {
|
|
216
|
+
/** One provider-neutral route created with createVideoChatHandler. */
|
|
217
|
+
endpoint?: string | URL;
|
|
218
|
+
/** Customer-owned templates that replace built-ins and add new renderers. */
|
|
219
|
+
templates?: TemplateRegistry;
|
|
220
|
+
mode?: VideoChatMode;
|
|
221
|
+
orientation?: VideoOrientation;
|
|
222
|
+
brand?: VideoBrandInput;
|
|
223
|
+
style?: VideoStyleOptions;
|
|
224
|
+
headers?: HeadersInit;
|
|
225
|
+
credentials?: RequestCredentials;
|
|
226
|
+
fetcher?: typeof fetch;
|
|
227
|
+
/** Replace the SDK speech client while keeping session timing and cancellation. */
|
|
228
|
+
voice?: VideoChatVoice;
|
|
229
|
+
initialMuted?: boolean;
|
|
230
|
+
timeoutMs?: number;
|
|
231
|
+
createTurnId?: () => string;
|
|
232
|
+
/** Observe how long a fresh response takes to display its first actual scene. */
|
|
233
|
+
onFirstFrame?: (metric: VideoChatFirstFrameMetric) => unknown;
|
|
234
|
+
}
|
|
235
|
+
interface VideoChatFirstFrameMetric {
|
|
236
|
+
turnId: string;
|
|
237
|
+
mode: VideoChatMode;
|
|
238
|
+
timeToFirstFrameMs: number;
|
|
239
|
+
}
|
|
240
|
+
interface UseVideoChatResult {
|
|
241
|
+
ask(prompt: string, options?: VideoChatAskOptions): Promise<Video | undefined>;
|
|
242
|
+
cancel(reason?: string): void;
|
|
243
|
+
pause(): void;
|
|
244
|
+
resume(): void;
|
|
245
|
+
replay(): void;
|
|
246
|
+
selectTurn(id: string): void;
|
|
247
|
+
reset(): void;
|
|
248
|
+
turns: readonly VideoChatTurn[];
|
|
249
|
+
currentTurn?: VideoChatTurn;
|
|
250
|
+
shownTurn?: VideoChatTurn;
|
|
251
|
+
capabilities?: VideoChatCapabilities;
|
|
252
|
+
welcome?: VideoChatWelcome;
|
|
253
|
+
availableModes: readonly VideoChatMode[];
|
|
254
|
+
status: VideoChatStatus;
|
|
255
|
+
error?: VideoError;
|
|
256
|
+
suggestions: readonly VideoChatSuggestion[];
|
|
257
|
+
caption?: string;
|
|
258
|
+
/** Narration revealed so far for the shown response. */
|
|
259
|
+
transcript: readonly string[];
|
|
260
|
+
speaking: boolean;
|
|
261
|
+
muted: boolean;
|
|
262
|
+
setMuted(muted: boolean): void;
|
|
263
|
+
playbackEnded: boolean;
|
|
264
|
+
/** Changes whenever saved content should restart from zero. */
|
|
265
|
+
playerKey: number;
|
|
266
|
+
/** Spread into VideoPlayer when present. */
|
|
267
|
+
playerProps?: VideoPlayerProps;
|
|
268
|
+
}
|
|
269
|
+
/** Own a complete video conversation while the application owns its UI. */
|
|
270
|
+
declare function useVideoChat(options?: UseVideoChatOptions): UseVideoChatResult;
|
|
271
|
+
|
|
272
|
+
interface VideoChatProps {
|
|
273
|
+
/** Connection, providers, templates, and rendering defaults for the session. */
|
|
274
|
+
options?: UseVideoChatOptions;
|
|
275
|
+
/** Added to the scoped component root for application layout and branding. */
|
|
276
|
+
className?: string;
|
|
277
|
+
/** Replaces the default two-line welcome heading without changing the interaction. */
|
|
278
|
+
welcomeTitle?: ReactNode;
|
|
279
|
+
}
|
|
280
|
+
/** A complete voice-and-video chat interface backed by createVideoChatHandler. */
|
|
281
|
+
declare function VideoChat({ options, className, welcomeTitle }: VideoChatProps): react.JSX.Element;
|
|
282
|
+
|
|
283
|
+
export { type CreateVideoChatVoiceOptions, type Narration, type NarrationOptions, type NarrationVoice, type UseVideoChatOptions, type UseVideoChatResult, type UseVideoOptions, type UseVideoResult, VideoChat, VideoChatAskOptions, VideoChatCapabilities, type VideoChatFirstFrameMetric, VideoChatMedia, VideoChatMode, type VideoChatPreparedSpeech, type VideoChatProps, type VideoChatStatus, VideoChatSuggestion, type VideoChatTurn, type VideoChatVoice, VideoChatWelcome, VideoError, type VideoErrorOptions, type VideoPlaybackMode, VideoPlayer, type VideoPlayerProps, createVideoChatVoice, useNarration, useVideo, useVideoChat };
|