@voqalize/avatar 0.0.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/LICENSE +661 -0
- package/README.md +692 -0
- package/client/dist/Avatar.d.ts +24 -0
- package/client/dist/Avatar.d.ts.map +1 -0
- package/client/dist/Avatar.js +7 -0
- package/client/dist/Avatar.js.map +1 -0
- package/client/dist/AvatarClient.d.ts +173 -0
- package/client/dist/AvatarClient.d.ts.map +1 -0
- package/client/dist/AvatarClient.js +274 -0
- package/client/dist/AvatarClient.js.map +1 -0
- package/client/dist/pipecat.d.ts +21 -0
- package/client/dist/pipecat.d.ts.map +1 -0
- package/client/dist/pipecat.js +21 -0
- package/client/dist/pipecat.js.map +1 -0
- package/client/dist/react.d.ts +16 -0
- package/client/dist/react.d.ts.map +1 -0
- package/client/dist/react.js +17 -0
- package/client/dist/react.js.map +1 -0
- package/client/dist/types.d.ts +101 -0
- package/client/dist/types.d.ts.map +1 -0
- package/client/dist/types.js +31 -0
- package/client/dist/types.js.map +1 -0
- package/client/dist/useAvatar.d.ts +53 -0
- package/client/dist/useAvatar.d.ts.map +1 -0
- package/client/dist/useAvatar.js +68 -0
- package/client/dist/useAvatar.js.map +1 -0
- package/client/src/Avatar.tsx +38 -0
- package/client/src/AvatarClient.ts +343 -0
- package/client/src/pipecat.ts +38 -0
- package/client/src/react.ts +34 -0
- package/client/src/types.ts +127 -0
- package/client/src/useAvatar.ts +113 -0
- package/docs/contract-avatar.md +337 -0
- package/docs/contract-protocol.md +401 -0
- package/package.json +89 -0
- package/src/audio-fallback.js +100 -0
- package/src/avatar.d.ts +241 -0
- package/src/avatar.js +722 -0
- package/src/clips.js +144 -0
- package/src/emotions.js +55 -0
- package/src/face-core.js +154 -0
- package/src/face-myna.js +725 -0
- package/src/face-peep.js +767 -0
- package/src/face-wren.js +470 -0
- package/src/gaze.js +155 -0
- package/src/idle.js +535 -0
- package/src/interjections.js +578 -0
- package/src/line-art.js +111 -0
- package/src/params.js +176 -0
- package/src/perform.js +105 -0
- package/src/visemes.js +230 -0
package/src/avatar.d.ts
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* avatar.d.ts — hand-maintained types for the widget's public surface.
|
|
3
|
+
*
|
|
4
|
+
* The widget is dependency-free ES modules with no build step, so there is no
|
|
5
|
+
* compiler to derive these from; this file is written by hand against
|
|
6
|
+
* `docs/contract-protocol.md` (the binding server ↔ widget contract) and a
|
|
7
|
+
* reading of `avatar.js`. It lives here rather than in a consumer because it
|
|
8
|
+
* is only correct next to the code it describes — the previous copy lived in
|
|
9
|
+
* a vendored tree two repos away and went stale the first time an enum grew.
|
|
10
|
+
*
|
|
11
|
+
* It is deliberately not a conversion of the widget to TypeScript. String-keyed
|
|
12
|
+
* enums (state / gaze / emotion / interjection ids) are literal unions for
|
|
13
|
+
* editor ergonomics, but every setter also accepts plain `string`, because the
|
|
14
|
+
* widget enforces these enums itself at runtime — unknown state and
|
|
15
|
+
* interjection ids throw, unknown emotion and gaze fall back silently — and a
|
|
16
|
+
* stale `.d.ts` must never claim to be stricter than the code it describes.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/** `STATE_NAMES` — see docs/contract-protocol.md § States. */
|
|
20
|
+
export type AvatarStateName =
|
|
21
|
+
| "IDLE"
|
|
22
|
+
| "LISTENING"
|
|
23
|
+
| "THINKING"
|
|
24
|
+
| "SPEAKING"
|
|
25
|
+
| "REVIEWING_SCREEN"
|
|
26
|
+
| "WAITING_FOR_USER"
|
|
27
|
+
| "TYPING"
|
|
28
|
+
| "TYPING_CHAT"
|
|
29
|
+
| "DISTRACTED"
|
|
30
|
+
| "SEARCHING_SCREEN"
|
|
31
|
+
| "CANT_HEAR"
|
|
32
|
+
| "TAKING_FLOOR"
|
|
33
|
+
| "WANTS_IN"
|
|
34
|
+
| "YIELDED"
|
|
35
|
+
| "DEGRADED"
|
|
36
|
+
| "OFFLINE";
|
|
37
|
+
|
|
38
|
+
/** `EMOTION_NAMES` — see docs/contract-protocol.md § Emotion. */
|
|
39
|
+
export type AvatarEmotionName =
|
|
40
|
+
| "neutral"
|
|
41
|
+
| "warm"
|
|
42
|
+
| "curious"
|
|
43
|
+
| "concerned"
|
|
44
|
+
| "encouraging"
|
|
45
|
+
| "thoughtful";
|
|
46
|
+
|
|
47
|
+
/** `GAZE_NAMES` — see docs/contract-protocol.md § Gaze. `"CUSTOM"` is the escape hatch (any name + a `custom` point works). */
|
|
48
|
+
export type AvatarGazeName =
|
|
49
|
+
| "USER"
|
|
50
|
+
| "USER_EAR"
|
|
51
|
+
| "SCREEN_CENTER"
|
|
52
|
+
| "SCREEN_LEFT"
|
|
53
|
+
| "SCREEN_RIGHT"
|
|
54
|
+
| "SCREEN_TOP"
|
|
55
|
+
| "SCREEN_BOTTOM"
|
|
56
|
+
| "SCREEN_WORK"
|
|
57
|
+
| "NOTES"
|
|
58
|
+
| "AWAY_THINKING"
|
|
59
|
+
| "AWAY_RIGHT"
|
|
60
|
+
| "AWAY_DOWN"
|
|
61
|
+
| "CUSTOM";
|
|
62
|
+
|
|
63
|
+
/** `INTERJECTION_IDS` — see docs/contract-protocol.md § Interjections. */
|
|
64
|
+
export type AvatarInterjectionId =
|
|
65
|
+
| "NOD_SMALL"
|
|
66
|
+
| "NOD_SLOW"
|
|
67
|
+
| "NOD_UP"
|
|
68
|
+
| "BROW_ACK"
|
|
69
|
+
| "HEAD_SHAKE"
|
|
70
|
+
| "HEAD_SHAKE_SOFT"
|
|
71
|
+
| "BLINK_LONG"
|
|
72
|
+
| "CLAIM_FLOOR"
|
|
73
|
+
| "YIELD_FLOOR"
|
|
74
|
+
| "RAISE_HAND"
|
|
75
|
+
| "WAVE"
|
|
76
|
+
| "THUMBS_UP"
|
|
77
|
+
| "SHRUG"
|
|
78
|
+
| "GO_ON_ARM"
|
|
79
|
+
| "MM_HMM"
|
|
80
|
+
| "OKAY"
|
|
81
|
+
| "YES"
|
|
82
|
+
| "SURE"
|
|
83
|
+
| "I_SEE"
|
|
84
|
+
| "RIGHT"
|
|
85
|
+
| "GO_ON"
|
|
86
|
+
| "ONE_MOMENT"
|
|
87
|
+
| "SORRY"
|
|
88
|
+
| "HMM"
|
|
89
|
+
| "GOT_IT"
|
|
90
|
+
| "TAKE_YOUR_TIME";
|
|
91
|
+
|
|
92
|
+
/** Rhubarb Lip Sync letter — see docs/contract-protocol.md § Speech. */
|
|
93
|
+
export type VisemeLetter = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "X";
|
|
94
|
+
|
|
95
|
+
/** One viseme cue: `t` is a ms offset into the utterance, `i` is optional 0..1 loudness. */
|
|
96
|
+
export interface Cue {
|
|
97
|
+
t: number;
|
|
98
|
+
v: string;
|
|
99
|
+
i?: number;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Normalized-screen-coordinate escape hatch for `setGaze('CUSTOM', custom)`. */
|
|
103
|
+
export interface GazeCustom {
|
|
104
|
+
x: number;
|
|
105
|
+
y: number;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** A `perform()` timeline action — see docs/contract-protocol.md § Composing behavior. */
|
|
109
|
+
export interface AvatarAction {
|
|
110
|
+
t: number;
|
|
111
|
+
do: "state" | "emotion" | "gaze" | "interject";
|
|
112
|
+
name?: string;
|
|
113
|
+
id?: string;
|
|
114
|
+
i?: number;
|
|
115
|
+
keepGaze?: boolean;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface SetStateOptions {
|
|
119
|
+
emotion?: AvatarEmotionName | (string & {});
|
|
120
|
+
intensity?: number;
|
|
121
|
+
gaze?: AvatarGazeName | (string & {});
|
|
122
|
+
keepGaze?: boolean;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface SpeakOptions {
|
|
126
|
+
cues?: Cue[];
|
|
127
|
+
audio?: HTMLMediaElement;
|
|
128
|
+
clock?: () => number;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface PerformOptions {
|
|
132
|
+
audio?: HTMLMediaElement;
|
|
133
|
+
clock?: () => number;
|
|
134
|
+
onAction?: (a: AvatarAction) => void;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface PerformHandle {
|
|
138
|
+
/** Cancels the *future* of this performance only — see docs/contract-protocol.md. */
|
|
139
|
+
stop: () => void;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export type AvatarEventName = "state" | "speakEnd" | "clipEnd" | "backchannel" | "performEnd";
|
|
143
|
+
|
|
144
|
+
/** What a host needs to frame an avatar it has never seen: the drawing's own
|
|
145
|
+
* window, and where the mouth is inside it. See CLAUDE.md § The two
|
|
146
|
+
* abstractions that matter for why it carries nothing else. */
|
|
147
|
+
export interface AvatarMeta {
|
|
148
|
+
viewBox: { x: number; y: number; w: number; h: number };
|
|
149
|
+
mouthCrop?: { x: number; y: number; w: number; h: number };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** The object `createAvatar()` returns — the whole server-facing surface. */
|
|
153
|
+
export interface AvatarApi {
|
|
154
|
+
setState(name: AvatarStateName | (string & {}), o?: SetStateOptions): AvatarApi;
|
|
155
|
+
setEmotion(name: AvatarEmotionName | (string & {}), intensity?: number): AvatarApi;
|
|
156
|
+
setGaze(name: AvatarGazeName | (string & {}), custom?: GazeCustom): AvatarApi;
|
|
157
|
+
speak(o?: SpeakOptions): AvatarApi;
|
|
158
|
+
pushCues(cues: Cue[]): AvatarApi;
|
|
159
|
+
stopSpeaking(): AvatarApi;
|
|
160
|
+
interject(id: AvatarInterjectionId | (string & {})): AvatarApi;
|
|
161
|
+
perform(actions: AvatarAction[], o?: PerformOptions): PerformHandle;
|
|
162
|
+
setAudioFallback(source?: HTMLMediaElement | MediaStream | null): AvatarApi;
|
|
163
|
+
setUserAudio(source?: HTMLMediaElement | MediaStream | null): AvatarApi;
|
|
164
|
+
setUserSpeaking(speaking: boolean | null): AvatarApi;
|
|
165
|
+
setMouthGain(g: number): AvatarApi;
|
|
166
|
+
readonly mouthGain: number;
|
|
167
|
+
setGestureGain(g: number): AvatarApi;
|
|
168
|
+
readonly gestureGain: number;
|
|
169
|
+
blink(double?: boolean): AvatarApi;
|
|
170
|
+
setOverrides(o: Record<string, number> | null): AvatarApi;
|
|
171
|
+
on(event: "state", fn: (name: AvatarStateName) => void): AvatarApi;
|
|
172
|
+
on(event: "speakEnd" | "performEnd", fn: () => void): AvatarApi;
|
|
173
|
+
on(event: "clipEnd" | "backchannel", fn: (id: string) => void): AvatarApi;
|
|
174
|
+
on(event: AvatarEventName, fn: (...args: unknown[]) => void): AvatarApi;
|
|
175
|
+
readonly state: AvatarStateName;
|
|
176
|
+
readonly emotion: AvatarEmotionName;
|
|
177
|
+
readonly gaze: AvatarGazeName;
|
|
178
|
+
readonly speaking: boolean;
|
|
179
|
+
readonly performing: boolean;
|
|
180
|
+
readonly clip: string | null;
|
|
181
|
+
readonly params: Record<string, number>;
|
|
182
|
+
readonly audioLevel: number;
|
|
183
|
+
readonly userSpeaking: boolean;
|
|
184
|
+
readonly svg: SVGSVGElement;
|
|
185
|
+
readonly meta: AvatarMeta;
|
|
186
|
+
destroy(): void;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** A face module's factory — `createFace(mount, theme)`. See
|
|
190
|
+
* docs/contract-avatar.md § Adding a new avatar. */
|
|
191
|
+
export type FaceFactory = (
|
|
192
|
+
mount: Element,
|
|
193
|
+
theme?: unknown,
|
|
194
|
+
) => {
|
|
195
|
+
svg: SVGSVGElement;
|
|
196
|
+
apply: (params: Record<string, number>) => void;
|
|
197
|
+
theme: unknown;
|
|
198
|
+
destroy: () => void;
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
export interface CreateAvatarOptions {
|
|
202
|
+
/** Element, or CSS selector resolved via `document.querySelector`. */
|
|
203
|
+
mount: string | Element;
|
|
204
|
+
/** Name from `AVATAR_NAMES`. Defaults to `DEFAULT_AVATAR`. */
|
|
205
|
+
avatar?: string;
|
|
206
|
+
/** A bare face factory, for an avatar the registry doesn't know about.
|
|
207
|
+
* `meta` then falls back to the svg's own viewBox. */
|
|
208
|
+
face?: FaceFactory;
|
|
209
|
+
theme?: unknown;
|
|
210
|
+
mouthGain?: number;
|
|
211
|
+
gestureGain?: number;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function createAvatar(opts: CreateAvatarOptions): AvatarApi;
|
|
215
|
+
|
|
216
|
+
/** The registry: `{ create, meta }` per avatar. */
|
|
217
|
+
export const AVATARS: Record<string, { create: FaceFactory; meta: AvatarMeta }>;
|
|
218
|
+
export const AVATAR_NAMES: string[];
|
|
219
|
+
export const DEFAULT_AVATAR: string;
|
|
220
|
+
|
|
221
|
+
/** Per-state base pose + idle profile. Read-only in practice — the mixer owns it. */
|
|
222
|
+
export const STATES: Record<string, Record<string, unknown>>;
|
|
223
|
+
export const STATE_NAMES: AvatarStateName[];
|
|
224
|
+
export const GAZE_NAMES: AvatarGazeName[];
|
|
225
|
+
export const GAZE_TARGETS: Record<string, { x: number; y: number }>;
|
|
226
|
+
export const EMOTION_NAMES: AvatarEmotionName[];
|
|
227
|
+
export const INTERJECTIONS: Record<string, unknown>;
|
|
228
|
+
export const INTERJECTION_IDS: AvatarInterjectionId[];
|
|
229
|
+
/** The subset that has (or expects) audio — the rest are silent gestures. */
|
|
230
|
+
export const SPOKEN_IDS: AvatarInterjectionId[];
|
|
231
|
+
export const VISEME_LETTERS: VisemeLetter[];
|
|
232
|
+
export const VISEME_SHAPES: Record<string, Record<string, number>>;
|
|
233
|
+
/** Cues lead the audio by this many ms — perceptual tolerance is asymmetric. */
|
|
234
|
+
export const LEAD_MS: number;
|
|
235
|
+
export const ARPABET_TO_VISEME: Record<string, string>;
|
|
236
|
+
export const AZURE_VISEME_TO_LETTER: Record<number, string>;
|
|
237
|
+
|
|
238
|
+
export function attachAudio(id: string, url: string): void;
|
|
239
|
+
export function normalizeActions(actions: AvatarAction[]): AvatarAction[];
|
|
240
|
+
export function normalizeCues(cues: Cue[]): Cue[];
|
|
241
|
+
export function textToCues(text: string, opts?: { wpm?: number }): Cue[];
|