@voqalize/avatar 0.5.5 → 0.5.7
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/README.md +32 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +67 -2
- package/dist/pin.d.ts +1 -1
- package/dist/pin.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -71,6 +71,38 @@ The gains are optional, from `0` to `2`, and `1` is as authored:
|
|
|
71
71
|
|
|
72
72
|
The client must be connected to a Voqalize session that has the avatar turned on.
|
|
73
73
|
|
|
74
|
+
## Preload before the call
|
|
75
|
+
|
|
76
|
+
Building a face takes the browser a moment: the runtime, the character, a GPU
|
|
77
|
+
context and its shaders. On a slow phone that is over a second after the call
|
|
78
|
+
connects before the face appears. `preloadAvatar` does that work before the call, off screen, so the
|
|
79
|
+
mount that follows only moves the finished face onto the page:
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
import { preloadAvatar, unloadAvatar } from "@voqalize/avatar";
|
|
83
|
+
|
|
84
|
+
// when the visitor is about to talk: the page with the call button, or hover on it
|
|
85
|
+
const face = preloadAvatar("<name>");
|
|
86
|
+
|
|
87
|
+
// later, the ordinary mount takes the preloaded face
|
|
88
|
+
createAvatar({ mount, client, character: "<name>" });
|
|
89
|
+
|
|
90
|
+
// or, if the visitor leaves without calling
|
|
91
|
+
unloadAvatar(face);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- One face is held at a time. Preloading the same character again returns the
|
|
95
|
+
same handle; preloading another frees the one held.
|
|
96
|
+
- A mount of that character, through `createAvatar` or `<Avatar>`, takes the
|
|
97
|
+
face. After that the handle holds nothing and `unloadAvatar` does nothing,
|
|
98
|
+
and `destroy()` frees the face as usual.
|
|
99
|
+
- `face.ready` settles when the face is built, or when it cannot be (no
|
|
100
|
+
WebGL 2, for example) and the mount will build it the ordinary way. You
|
|
101
|
+
never need to wait for it before mounting. It rejects only for a name that is
|
|
102
|
+
no character.
|
|
103
|
+
- `unloadAvatar` frees the GPU context and the character's memory at once,
|
|
104
|
+
and is safe to call at any time.
|
|
105
|
+
|
|
74
106
|
### React
|
|
75
107
|
|
|
76
108
|
```jsx
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
*
|
|
10
10
|
* const roster = await listCharacters(); // every character, to choose from
|
|
11
11
|
*
|
|
12
|
+
* const face = preloadAvatar("tara"); // before the call: build it off screen
|
|
13
|
+
* await face.ready; // optional; createAvatar takes it either way
|
|
14
|
+
* unloadAvatar(face); // the visitor left without calling
|
|
15
|
+
*
|
|
12
16
|
* This package is the loader and nothing else. The avatar itself — the
|
|
13
17
|
* characters, the renderer and everything that reads the call — is the
|
|
14
18
|
* Voqalize avatar runtime, which this module imports from
|
|
@@ -67,6 +71,14 @@ export interface CharacterInfo {
|
|
|
67
71
|
* for example. Advice only: the avatar never speaks. */
|
|
68
72
|
readonly suggestedVoices: readonly string[];
|
|
69
73
|
}
|
|
74
|
+
/** A face `preloadAvatar` is building, or has built, ahead of its mount. */
|
|
75
|
+
export interface PreloadedAvatar {
|
|
76
|
+
/** The character it is. */
|
|
77
|
+
readonly character: string;
|
|
78
|
+
/** Settles once the face is built, or once it cannot be and the mount will
|
|
79
|
+
* build it the ordinary way. Rejects only for a name that is no character. */
|
|
80
|
+
readonly ready: Promise<void>;
|
|
81
|
+
}
|
|
70
82
|
export declare function createAvatar(options: AvatarOptions): AvatarInstance;
|
|
71
83
|
/**
|
|
72
84
|
* Every character the runtime can mount, in a stable order — for a page that
|
|
@@ -75,3 +87,26 @@ export declare function createAvatar(options: AvatarOptions): AvatarInstance;
|
|
|
75
87
|
* runtime's own and cannot be changed.
|
|
76
88
|
*/
|
|
77
89
|
export declare function listCharacters(): Promise<readonly CharacterInfo[]>;
|
|
90
|
+
/**
|
|
91
|
+
* Build a character's face before there is anywhere to show it — the runtime,
|
|
92
|
+
* the character, its GPU context, its shaders and a first frame — so that a
|
|
93
|
+
* `createAvatar` (or `<Avatar>`) of the same character later only moves it onto
|
|
94
|
+
* the page. Call it when the visitor shows they are about to talk: on the page
|
|
95
|
+
* that holds the call button, or on hover over it.
|
|
96
|
+
*
|
|
97
|
+
* Holds one face. The same character again returns the same handle; another
|
|
98
|
+
* character frees the one held and builds the new one. A mount of the
|
|
99
|
+
* character takes the face, and the handle no longer holds anything. Nothing
|
|
100
|
+
* else changes for a mount: one with no preload, or of another character,
|
|
101
|
+
* builds its face as it always has.
|
|
102
|
+
*/
|
|
103
|
+
export declare function preloadAvatar(character: string): PreloadedAvatar;
|
|
104
|
+
/**
|
|
105
|
+
* Free the face `preloadAvatar` built: its GPU context, the decoded character
|
|
106
|
+
* and its textures. For a visitor who leaves without calling, or a page that
|
|
107
|
+
* will not mount it after all. A handle a mount has taken, or that a preload
|
|
108
|
+
* of another character has already replaced, holds nothing, and unloading it
|
|
109
|
+
* does nothing. Safe to call at any time, including before `ready` settles;
|
|
110
|
+
* it then settles without the face being built, or with the build abandoned.
|
|
111
|
+
*/
|
|
112
|
+
export declare function unloadAvatar(face: PreloadedAvatar): void;
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
*
|
|
10
10
|
* const roster = await listCharacters(); // every character, to choose from
|
|
11
11
|
*
|
|
12
|
+
* const face = preloadAvatar("tara"); // before the call: build it off screen
|
|
13
|
+
* await face.ready; // optional; createAvatar takes it either way
|
|
14
|
+
* unloadAvatar(face); // the visitor left without calling
|
|
15
|
+
*
|
|
12
16
|
* This package is the loader and nothing else. The avatar itself — the
|
|
13
17
|
* characters, the renderer and everything that reads the call — is the
|
|
14
18
|
* Voqalize avatar runtime, which this module imports from
|
|
@@ -44,8 +48,13 @@ export function createAvatar(options) {
|
|
|
44
48
|
let destroyed = false;
|
|
45
49
|
load()
|
|
46
50
|
.then((rt) => {
|
|
47
|
-
if (
|
|
48
|
-
|
|
51
|
+
if (destroyed)
|
|
52
|
+
return;
|
|
53
|
+
// The runtime moves a preloaded face of this character into the mount,
|
|
54
|
+
// after which it is the avatar's to destroy and no handle's to unload.
|
|
55
|
+
if (held?.character === options.character)
|
|
56
|
+
held = undefined;
|
|
57
|
+
instance = rt.mount({ ...options, protocol: PROTOCOL });
|
|
49
58
|
})
|
|
50
59
|
.catch((error) => console.error(`[avatar] could not start the avatar from ${RUNTIME_URL}`, error));
|
|
51
60
|
return {
|
|
@@ -68,3 +77,59 @@ export async function listCharacters() {
|
|
|
68
77
|
throw new Error(`[avatar] the runtime at ${RUNTIME_URL} does not list its characters`);
|
|
69
78
|
return rt.characters();
|
|
70
79
|
}
|
|
80
|
+
// The one face built ahead of its mount. One, not one per character: each
|
|
81
|
+
// holds a GPU context and a decoded head, and a page about to call knows
|
|
82
|
+
// which character it is about to show.
|
|
83
|
+
let held;
|
|
84
|
+
/**
|
|
85
|
+
* Build a character's face before there is anywhere to show it — the runtime,
|
|
86
|
+
* the character, its GPU context, its shaders and a first frame — so that a
|
|
87
|
+
* `createAvatar` (or `<Avatar>`) of the same character later only moves it onto
|
|
88
|
+
* the page. Call it when the visitor shows they are about to talk: on the page
|
|
89
|
+
* that holds the call button, or on hover over it.
|
|
90
|
+
*
|
|
91
|
+
* Holds one face. The same character again returns the same handle; another
|
|
92
|
+
* character frees the one held and builds the new one. A mount of the
|
|
93
|
+
* character takes the face, and the handle no longer holds anything. Nothing
|
|
94
|
+
* else changes for a mount: one with no preload, or of another character,
|
|
95
|
+
* builds its face as it always has.
|
|
96
|
+
*/
|
|
97
|
+
export function preloadAvatar(character) {
|
|
98
|
+
if (!character)
|
|
99
|
+
throw new TypeError("preloadAvatar: `character` is required");
|
|
100
|
+
if (held?.character === character)
|
|
101
|
+
return held;
|
|
102
|
+
if (held)
|
|
103
|
+
unloadAvatar(held);
|
|
104
|
+
const face = {
|
|
105
|
+
character,
|
|
106
|
+
ready: load().then((rt) => (held === face ? rt.preload?.(character) : undefined),
|
|
107
|
+
// A runtime that will not load leaves the mount to try again and report
|
|
108
|
+
// it; a preload is never the reason a page cannot call.
|
|
109
|
+
(error) => {
|
|
110
|
+
if (held === face)
|
|
111
|
+
held = undefined;
|
|
112
|
+
console.error(`[avatar] could not preload the avatar from ${RUNTIME_URL}`, error);
|
|
113
|
+
}).then(() => undefined, (error) => {
|
|
114
|
+
if (held === face)
|
|
115
|
+
held = undefined;
|
|
116
|
+
throw error;
|
|
117
|
+
}),
|
|
118
|
+
};
|
|
119
|
+
held = face;
|
|
120
|
+
return face;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Free the face `preloadAvatar` built: its GPU context, the decoded character
|
|
124
|
+
* and its textures. For a visitor who leaves without calling, or a page that
|
|
125
|
+
* will not mount it after all. A handle a mount has taken, or that a preload
|
|
126
|
+
* of another character has already replaced, holds nothing, and unloading it
|
|
127
|
+
* does nothing. Safe to call at any time, including before `ready` settles;
|
|
128
|
+
* it then settles without the face being built, or with the build abandoned.
|
|
129
|
+
*/
|
|
130
|
+
export function unloadAvatar(face) {
|
|
131
|
+
if (!face || held !== face)
|
|
132
|
+
return;
|
|
133
|
+
held = undefined;
|
|
134
|
+
load().then((rt) => rt.unload?.(face.character), () => { });
|
|
135
|
+
}
|
package/dist/pin.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const RUNTIME_URL = "https://avatar.voqalize.com/runtime/runtime.
|
|
1
|
+
export declare const RUNTIME_URL = "https://avatar.voqalize.com/runtime/runtime.UTAI5EKI.js";
|
|
2
2
|
export declare const PROTOCOL = 1;
|
package/dist/pin.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// Written by scripts/build-runtime.mjs — the runtime this shim is released with.
|
|
2
|
-
export const RUNTIME_URL = "https://avatar.voqalize.com/runtime/runtime.
|
|
2
|
+
export const RUNTIME_URL = "https://avatar.voqalize.com/runtime/runtime.UTAI5EKI.js";
|
|
3
3
|
export const PROTOCOL = 1;
|
package/package.json
CHANGED