@zeroweight/renderer 0.2.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/README.md +158 -0
- package/dist/ActionQueue.d.ts +85 -0
- package/dist/ActionQueue.d.ts.map +1 -0
- package/dist/VoiceActivityDetector.d.ts +54 -0
- package/dist/VoiceActivityDetector.d.ts.map +1 -0
- package/dist/ZeroWeightRenderer.d.ts +78 -0
- package/dist/ZeroWeightRenderer.d.ts.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/types.d.ts +68 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/zeroweight-renderer.es.js +2 -0
- package/dist/zeroweight-renderer.es.js.map +1 -0
- package/dist/zeroweight-renderer.umd.js +3 -0
- package/dist/zeroweight-renderer.umd.js.map +1 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# @zeroweight/renderer
|
|
2
|
+
|
|
3
|
+
Universal avatar rendering engine. Framework-agnostic — use via CDN `<script>` tag or ES module import.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### CDN (Script Tag)
|
|
8
|
+
|
|
9
|
+
```html
|
|
10
|
+
<script src="https://unpkg.com/@zeroweight/renderer/dist/zeroweight-renderer.umd.js"></script>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or via jsDelivr:
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<script src="https://cdn.jsdelivr.net/npm/@zeroweight/renderer/dist/zeroweight-renderer.umd.js"></script>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### npm / yarn
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @zeroweight/renderer
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
### Via `<script>` tag
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<canvas id="avatar" width="640" height="480"></canvas>
|
|
31
|
+
|
|
32
|
+
<script src="https://unpkg.com/@zeroweight/renderer/dist/zeroweight-renderer.umd.js"></script>
|
|
33
|
+
<script>
|
|
34
|
+
const { ZeroWeightRenderer, ActionQueue, VoiceActivityDetector } = window.ZeroWeightRenderer;
|
|
35
|
+
|
|
36
|
+
const renderer = new ZeroWeightRenderer();
|
|
37
|
+
const canvas = document.getElementById('avatar');
|
|
38
|
+
|
|
39
|
+
// Init with your avatar bundle payload
|
|
40
|
+
await renderer.init(canvas, { payload: bundleData });
|
|
41
|
+
|
|
42
|
+
// Play actions
|
|
43
|
+
renderer.play('speaking');
|
|
44
|
+
renderer.play('wave_hand', 'listening'); // oneshot with fallback
|
|
45
|
+
|
|
46
|
+
// Clean up
|
|
47
|
+
renderer.destroy();
|
|
48
|
+
</script>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Via ES module
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
import {
|
|
55
|
+
ZeroWeightRenderer,
|
|
56
|
+
ActionQueue,
|
|
57
|
+
VoiceActivityDetector,
|
|
58
|
+
} from "@zeroweight/renderer";
|
|
59
|
+
|
|
60
|
+
const renderer = new ZeroWeightRenderer();
|
|
61
|
+
await renderer.init(canvas, { payload: bundleData });
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## API
|
|
65
|
+
|
|
66
|
+
### `ZeroWeightRenderer`
|
|
67
|
+
|
|
68
|
+
The core rendering engine. Handles WASM initialization, canvas setup, render loop, and action management.
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
const renderer = new ZeroWeightRenderer();
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
| Method | Description |
|
|
75
|
+
| --------------------------- | -------------------------------------------------- |
|
|
76
|
+
| `init(canvas, config)` | Initialize with a canvas element and bundle config |
|
|
77
|
+
| `play(actionId, fallback?)` | Play an action (e.g. `"speaking"`, `"wave_hand"`) |
|
|
78
|
+
| `interrupt()` | Interrupt the current action |
|
|
79
|
+
| `destroy()` | Clean up all resources |
|
|
80
|
+
|
|
81
|
+
| Property | Description |
|
|
82
|
+
| ------------ | ---------------------------------------------------------------- |
|
|
83
|
+
| `state` | Current state: `"idle"` \| `"loading"` \| `"ready"` \| `"error"` |
|
|
84
|
+
| `isReady` | `true` when engine is ready |
|
|
85
|
+
| `dimensions` | Avatar intrinsic `{ width, height }` |
|
|
86
|
+
|
|
87
|
+
**Events:** `ready`, `actionLoaded`, `allActionsLoaded`, `dimensions`, `error`, `stateChanged`
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
renderer.on("ready", () => console.log("Engine ready!"));
|
|
91
|
+
renderer.on("dimensions", (w, h) => console.log(`Avatar: ${w}x${h}`));
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### `ActionQueue`
|
|
95
|
+
|
|
96
|
+
Centralized action dispatch with turn-based queuing for speech synchronization.
|
|
97
|
+
|
|
98
|
+
```js
|
|
99
|
+
const queue = new ActionQueue((actionId, fallback) => {
|
|
100
|
+
renderer.play(actionId, fallback);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
queue.dispatch("wave_hand"); // Execute or queue
|
|
104
|
+
queue.setTurnActive(true); // Start speaking turn
|
|
105
|
+
queue.setSpeechState("speaking"); // Update speech state
|
|
106
|
+
queue.forceListening(); // Reset to listening
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### `VoiceActivityDetector`
|
|
110
|
+
|
|
111
|
+
Amplitude-based VAD using Web Audio API with hysteresis for lipsync.
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
const vad = new VoiceActivityDetector({
|
|
115
|
+
threshold: 0.008,
|
|
116
|
+
speechStartFrames: 1,
|
|
117
|
+
speechPauseFrames: 30,
|
|
118
|
+
turnEndFrames: 50,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
vad.on("speechStart", () => queue.setTurnActive(true));
|
|
122
|
+
vad.on("turnEnd", () => queue.setTurnActive(false));
|
|
123
|
+
|
|
124
|
+
vad.start(mediaStreamTrack);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Usage Tiers
|
|
128
|
+
|
|
129
|
+
| Tier | What you get | Use case |
|
|
130
|
+
| ------------------ | ---------------------------------------------------------------------- | ------------------------ |
|
|
131
|
+
| **Tier 1 (Raw)** | `ZeroWeightRenderer` only | Custom engine control |
|
|
132
|
+
| **Tier 2 (Queue)** | + `ActionQueue` + `VoiceActivityDetector` | Speech-synced avatars |
|
|
133
|
+
| **Tier 3 (React)** | [`@zeroweight/react`](https://www.npmjs.com/package/@zeroweight/react) | Drop-in React components |
|
|
134
|
+
|
|
135
|
+
## Build from Source
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
git clone <repo-url>
|
|
139
|
+
cd zeroweight-renderer
|
|
140
|
+
npm install
|
|
141
|
+
npm run build
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Output in `dist/`:
|
|
145
|
+
|
|
146
|
+
- `zeroweight-renderer.umd.js` — UMD bundle (script tag)
|
|
147
|
+
- `zeroweight-renderer.es.js` — ES module
|
|
148
|
+
- `index.d.ts` — TypeScript declarations
|
|
149
|
+
|
|
150
|
+
## Deploy
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
npm publish --access public
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
MIT
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zeroweight-renderer — ActionQueue
|
|
3
|
+
*
|
|
4
|
+
* Centralized action dispatch + queue system.
|
|
5
|
+
* ALL calls to the rendering engine go through this single coordinator.
|
|
6
|
+
*
|
|
7
|
+
* Key concepts:
|
|
8
|
+
* - "Turn": The entire speaking episode. While a turn is active, non-speaking
|
|
9
|
+
* actions are queued and only executed after the turn ends.
|
|
10
|
+
* - "Speech state": Within a turn, the avatar can be "speaking" or "pause"
|
|
11
|
+
* (natural breath/pause). Pauses change the avatar's visual pose but don't
|
|
12
|
+
* drain the queue.
|
|
13
|
+
* - "Idle": No active turn. Actions execute immediately.
|
|
14
|
+
*/
|
|
15
|
+
import type { ActionMetadata, ActionQueueEvents, SpeechState } from "./types";
|
|
16
|
+
/** Function that actually executes an action on the engine. */
|
|
17
|
+
export type ActionExecutor = (actionId: string, fallbackAction?: string) => void;
|
|
18
|
+
export declare class ActionQueue {
|
|
19
|
+
private executor;
|
|
20
|
+
private turnActive;
|
|
21
|
+
private speechState;
|
|
22
|
+
private currentAction;
|
|
23
|
+
private pendingQueue;
|
|
24
|
+
private actionMetadata;
|
|
25
|
+
private pulseTimer;
|
|
26
|
+
private pulseCount;
|
|
27
|
+
private static readonly PULSE_INTERVAL_MS;
|
|
28
|
+
private static readonly PULSE_MAX_COUNT;
|
|
29
|
+
private listeners;
|
|
30
|
+
constructor(executor: ActionExecutor);
|
|
31
|
+
/**
|
|
32
|
+
* Register action metadata so the queue knows which actions are looped vs oneshot.
|
|
33
|
+
*/
|
|
34
|
+
setActionMetadata(metadata: Record<string, ActionMetadata>): void;
|
|
35
|
+
/**
|
|
36
|
+
* The SINGLE entry point for dispatching actions.
|
|
37
|
+
* All action requests MUST go through this method.
|
|
38
|
+
*/
|
|
39
|
+
dispatch(actionId: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Mark whether a speaking turn is active.
|
|
42
|
+
* When a turn starts, speaking actions execute immediately and non-speech
|
|
43
|
+
* actions are queued. When a turn ends, the queue is drained.
|
|
44
|
+
*/
|
|
45
|
+
setTurnActive(active: boolean): void;
|
|
46
|
+
/**
|
|
47
|
+
* Update the visual speech state within an active turn.
|
|
48
|
+
* "speaking" = avatar is speaking
|
|
49
|
+
* "pause" = natural pause, avatar goes to resting pose (but queue doesn't drain)
|
|
50
|
+
*/
|
|
51
|
+
setSpeechState(state: SpeechState): void;
|
|
52
|
+
/**
|
|
53
|
+
* Force transition to listening and clear the queue.
|
|
54
|
+
* Used on disconnect, audio loss, etc.
|
|
55
|
+
*/
|
|
56
|
+
forceListening(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Get current state for debugging/UI purposes.
|
|
59
|
+
*/
|
|
60
|
+
getState(): {
|
|
61
|
+
turnActive: boolean;
|
|
62
|
+
speechState: SpeechState;
|
|
63
|
+
currentAction: string;
|
|
64
|
+
queueLength: number;
|
|
65
|
+
queuedActions: string[];
|
|
66
|
+
};
|
|
67
|
+
on<K extends keyof ActionQueueEvents>(event: K, callback: ActionQueueEvents[K]): void;
|
|
68
|
+
off<K extends keyof ActionQueueEvents>(event: K, callback: ActionQueueEvents[K]): void;
|
|
69
|
+
private emit;
|
|
70
|
+
private isSpeechAction;
|
|
71
|
+
private executeOnEngine;
|
|
72
|
+
/**
|
|
73
|
+
* Pulse mechanism: re-sends the desired action multiple times at short intervals
|
|
74
|
+
* to ensure the renderer catches it after its 5-frame (~200ms) transition window.
|
|
75
|
+
* Duplicate triggers are idempotent on the renderer side — safe to call repeatedly.
|
|
76
|
+
*/
|
|
77
|
+
private startPulse;
|
|
78
|
+
private stopPulse;
|
|
79
|
+
/**
|
|
80
|
+
* Drain queued actions after a turn ends. Each queued action plays as a
|
|
81
|
+
* oneshot, then we return to listening.
|
|
82
|
+
*/
|
|
83
|
+
private drainQueue;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=ActionQueue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActionQueue.d.ts","sourceRoot":"","sources":["../src/ActionQueue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE9E,+DAA+D;AAC/D,MAAM,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;AAEjF,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAiB;IAGjC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,cAAc,CAAsC;IAK5D,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAM;IAC/C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAM;IAG7C,OAAO,CAAC,SAAS,CAAmE;gBAExE,QAAQ,EAAE,cAAc;IAMpC;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI;IAIjE;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IA6BhC;;;;OAIG;IACH,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IA2BpC;;;;OAIG;IACH,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAwBxC;;;OAGG;IACH,cAAc,IAAI,IAAI;IAUtB;;OAEG;IACH,QAAQ;;;;;;;IAYR,EAAE,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,IAAI;IAOrF,GAAG,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,IAAI;IAOtF,OAAO,CAAC,IAAI;IAWZ,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,eAAe;IAavB;;;;OAIG;IACH,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,SAAS;IAQjB;;;OAGG;IACH,OAAO,CAAC,UAAU;CAuCnB"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zeroweight-renderer — VoiceActivityDetector
|
|
3
|
+
*
|
|
4
|
+
* Amplitude-based VAD using Web Audio API with hysteresis to prevent
|
|
5
|
+
* flickering between speaking/listening states during natural speech pauses.
|
|
6
|
+
*
|
|
7
|
+
* State machine:
|
|
8
|
+
* IDLE ──(amplitude > threshold for N frames)──> SPEAKING
|
|
9
|
+
* SPEAKING ──(amplitude < threshold for M frames)──> PAUSED (turn stays active)
|
|
10
|
+
* PAUSED ──(amplitude > threshold for N frames)──> SPEAKING (resumed)
|
|
11
|
+
* PAUSED ──(amplitude < threshold for L frames total)──> IDLE (turn ended)
|
|
12
|
+
* SPEAKING ──(amplitude < threshold for L frames)──> IDLE (turn ended, skipped pause)
|
|
13
|
+
*
|
|
14
|
+
* "Pause" means the avatar can visually transition to a resting pose, but the
|
|
15
|
+
* speaking turn is still active (action queue is NOT drained).
|
|
16
|
+
* "Turn end" means the speaking turn is over and the action queue can drain.
|
|
17
|
+
*/
|
|
18
|
+
import type { VADConfig, VADEvents } from "./types";
|
|
19
|
+
type VADState = "idle" | "speaking" | "paused";
|
|
20
|
+
export declare class VoiceActivityDetector {
|
|
21
|
+
private config;
|
|
22
|
+
private state;
|
|
23
|
+
private audioCtx;
|
|
24
|
+
private analyser;
|
|
25
|
+
private source;
|
|
26
|
+
private dataArray;
|
|
27
|
+
private intervalId;
|
|
28
|
+
private aboveCount;
|
|
29
|
+
private belowCount;
|
|
30
|
+
private listeners;
|
|
31
|
+
constructor(config?: VADConfig);
|
|
32
|
+
/**
|
|
33
|
+
* Start monitoring a MediaStreamTrack for voice activity.
|
|
34
|
+
*/
|
|
35
|
+
start(track: MediaStreamTrack): void;
|
|
36
|
+
/**
|
|
37
|
+
* Stop monitoring and clean up resources.
|
|
38
|
+
*/
|
|
39
|
+
stop(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Force-end the current turn (e.g., when LiveKit state changes to non-speaking).
|
|
42
|
+
*/
|
|
43
|
+
endTurn(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Get the current VAD state.
|
|
46
|
+
*/
|
|
47
|
+
getState(): VADState;
|
|
48
|
+
on<K extends keyof VADEvents>(event: K, callback: VADEvents[K]): void;
|
|
49
|
+
off<K extends keyof VADEvents>(event: K, callback: VADEvents[K]): void;
|
|
50
|
+
private emit;
|
|
51
|
+
private analyse;
|
|
52
|
+
}
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=VoiceActivityDetector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VoiceActivityDetector.d.ts","sourceRoot":"","sources":["../src/VoiceActivityDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpD,KAAK,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC;AAW/C,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,KAAK,CAAoB;IAGjC,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,MAAM,CAA2C;IACzD,OAAO,CAAC,SAAS,CAA0C;IAG3D,OAAO,CAAC,UAAU,CAA+C;IAGjE,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,UAAU,CAAK;IAGvB,OAAO,CAAC,SAAS,CAAmD;gBAExD,MAAM,CAAC,EAAE,SAAS;IAM9B;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAsBpC;;OAEG;IACH,IAAI,IAAI,IAAI;IAqBZ;;OAEG;IACH,OAAO,IAAI,IAAI;IASf;;OAEG;IACH,QAAQ,IAAI,QAAQ;IAMpB,EAAE,CAAC,CAAC,SAAS,MAAM,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAOrE,GAAG,CAAC,CAAC,SAAS,MAAM,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAOtE,OAAO,CAAC,IAAI;IAWZ,OAAO,CAAC,OAAO;CAuDhB"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zeroweight-renderer — ZeroWeightRenderer
|
|
3
|
+
*
|
|
4
|
+
* Raw rendering engine wrapper. Framework-agnostic.
|
|
5
|
+
* Handles WASM initialization, canvas setup, render loop, action loading,
|
|
6
|
+
* and provides a clean API for playing actions.
|
|
7
|
+
*
|
|
8
|
+
* Usage (vanilla JS / CDN):
|
|
9
|
+
* const renderer = new ZeroWeightRenderer();
|
|
10
|
+
* await renderer.init(canvas, { payload: bundleData });
|
|
11
|
+
* renderer.play('speaking');
|
|
12
|
+
* renderer.play('wave_hand', 'listening');
|
|
13
|
+
* renderer.destroy();
|
|
14
|
+
*/
|
|
15
|
+
import type { RendererConfig, RendererEvents, RendererState, ActionMetadata } from "./types";
|
|
16
|
+
export declare class ZeroWeightRenderer {
|
|
17
|
+
private engine;
|
|
18
|
+
private canvas;
|
|
19
|
+
private container;
|
|
20
|
+
private rafId;
|
|
21
|
+
private resizeObserver;
|
|
22
|
+
private _state;
|
|
23
|
+
private loadedActions;
|
|
24
|
+
private actionMetadata;
|
|
25
|
+
private _dimensions;
|
|
26
|
+
private listeners;
|
|
27
|
+
private cancelled;
|
|
28
|
+
/**
|
|
29
|
+
* Initialize the renderer with a canvas and bundle config.
|
|
30
|
+
*
|
|
31
|
+
* @param canvas - The canvas element to render to.
|
|
32
|
+
* If inside a container, the canvas will auto-resize to fill it.
|
|
33
|
+
* @param config - Renderer configuration with bundle payload.
|
|
34
|
+
* @returns A promise that resolves when the engine is ready.
|
|
35
|
+
*/
|
|
36
|
+
init(canvas: HTMLCanvasElement, config: RendererConfig): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Play an action on the avatar.
|
|
39
|
+
*
|
|
40
|
+
* @param actionId - The action to play (e.g. "speaking", "wave_hand").
|
|
41
|
+
* @param fallbackAction - Optional fallback action to play after a oneshot.
|
|
42
|
+
*/
|
|
43
|
+
play(actionId: string, fallbackAction?: string): void;
|
|
44
|
+
/**
|
|
45
|
+
* Interrupt the current action.
|
|
46
|
+
*/
|
|
47
|
+
interrupt(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Load a single action by its config.
|
|
50
|
+
* Useful for lazy-loading actions after init.
|
|
51
|
+
*/
|
|
52
|
+
loadAction(id: string, config: any): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Destroy the renderer and clean up all resources.
|
|
55
|
+
*/
|
|
56
|
+
destroy(): void;
|
|
57
|
+
get state(): RendererState;
|
|
58
|
+
get dimensions(): {
|
|
59
|
+
width: number;
|
|
60
|
+
height: number;
|
|
61
|
+
} | null;
|
|
62
|
+
get isReady(): boolean;
|
|
63
|
+
getLoadedActions(): Set<string>;
|
|
64
|
+
getActionMetadata(): Record<string, ActionMetadata>;
|
|
65
|
+
/**
|
|
66
|
+
* Direct access to the underlying engine instance (advanced usage).
|
|
67
|
+
*/
|
|
68
|
+
getEngine(): any;
|
|
69
|
+
on<K extends keyof RendererEvents>(event: K, callback: RendererEvents[K]): void;
|
|
70
|
+
off<K extends keyof RendererEvents>(event: K, callback: RendererEvents[K]): void;
|
|
71
|
+
private emit;
|
|
72
|
+
private setState;
|
|
73
|
+
private startRenderLoop;
|
|
74
|
+
private setupResizeObserver;
|
|
75
|
+
private handleResize;
|
|
76
|
+
private loadRemainingActions;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=ZeroWeightRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ZeroWeightRenderer.d.ts","sourceRoot":"","sources":["../src/ZeroWeightRenderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,cAAc,EACf,MAAM,SAAS,CAAC;AAKjB,qBAAa,kBAAkB;IAE7B,OAAO,CAAC,MAAM,CAAkD;IAChE,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,SAAS,CAA4B;IAG7C,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,cAAc,CAA+B;IAGrD,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,cAAc,CAGpB;IACF,OAAO,CAAC,WAAW,CAAkD;IAGrE,OAAO,CAAC,SAAS,CAA6D;IAG9E,OAAO,CAAC,SAAS,CAAS;IAI1B;;;;;;;OAOG;IACG,IAAI,CAAC,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IA4D5E;;;;;OAKG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI;IAiBrD;;OAEG;IACH,SAAS,IAAI,IAAI;IAQjB;;;OAGG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAcxD;;OAEG;IACH,OAAO,IAAI,IAAI;IAuBf,IAAI,KAAK,IAAI,aAAa,CAEzB;IAED,IAAI,UAAU,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAEzD;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,gBAAgB,IAAI,GAAG,CAAC,MAAM,CAAC;IAI/B,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC;IAInD;;OAEG;IACH,SAAS,IAAI,GAAG;IAMhB,EAAE,CAAC,CAAC,SAAS,MAAM,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI;IAO/E,GAAG,CAAC,CAAC,SAAS,MAAM,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI;IAOhF,OAAO,CAAC,IAAI;IAWZ,OAAO,CAAC,QAAQ;IAMhB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,YAAY;YAmBN,oBAAoB;CA8CnC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zeroweight-renderer
|
|
3
|
+
*
|
|
4
|
+
* Universal avatar rendering library.
|
|
5
|
+
* Framework-agnostic — works via CDN <script> tag or ES module import.
|
|
6
|
+
*
|
|
7
|
+
* Usage tiers:
|
|
8
|
+
* Tier 1 (Raw): ZeroWeightRenderer only — play/interrupt/destroy
|
|
9
|
+
* Tier 2 (Queue): + ActionQueue for managed dispatch + VoiceActivityDetector for lipsync
|
|
10
|
+
* Tier 3 (React): Import from @zeroweight/react for full drop-in components
|
|
11
|
+
*/
|
|
12
|
+
export { ZeroWeightRenderer } from "./ZeroWeightRenderer";
|
|
13
|
+
export { ActionQueue } from "./ActionQueue";
|
|
14
|
+
export type { ActionExecutor } from "./ActionQueue";
|
|
15
|
+
export { VoiceActivityDetector } from "./VoiceActivityDetector";
|
|
16
|
+
export * from "./types";
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,cAAc,SAAS,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zeroweight-renderer — Types & Interfaces
|
|
3
|
+
*
|
|
4
|
+
* Framework-agnostic types for the avatar rendering library.
|
|
5
|
+
*/
|
|
6
|
+
export type ActionKind = "looped" | "oneshot" | "image";
|
|
7
|
+
export interface ActionMetadata {
|
|
8
|
+
kind: ActionKind;
|
|
9
|
+
}
|
|
10
|
+
export type RendererState = "idle" | "loading" | "ready" | "error";
|
|
11
|
+
export interface RendererConfig {
|
|
12
|
+
/** The bundle payload data (from API). */
|
|
13
|
+
payload: any;
|
|
14
|
+
/** Scale factor for mobile downscaling. Default: auto-detect. */
|
|
15
|
+
scale?: number;
|
|
16
|
+
/** Override mobile detection. */
|
|
17
|
+
forceMobile?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface RendererEvents {
|
|
20
|
+
/** Engine fully initialized and first action ("listening") is ready. */
|
|
21
|
+
ready: () => void;
|
|
22
|
+
/** A background action finished loading. */
|
|
23
|
+
actionLoaded: (actionId: string, remaining: number) => void;
|
|
24
|
+
/** All background actions have been loaded. */
|
|
25
|
+
allActionsLoaded: () => void;
|
|
26
|
+
/** Avatar intrinsic dimensions are known. */
|
|
27
|
+
dimensions: (width: number, height: number) => void;
|
|
28
|
+
/** An error occurred. */
|
|
29
|
+
error: (error: Error) => void;
|
|
30
|
+
/** Renderer state changed. */
|
|
31
|
+
stateChanged: (state: RendererState) => void;
|
|
32
|
+
}
|
|
33
|
+
export type SpeechState = "speaking" | "pause" | "idle";
|
|
34
|
+
export interface ActionQueueEvents {
|
|
35
|
+
/** An action was executed on the engine. */
|
|
36
|
+
actionExecuted: (actionId: string, fallback?: string) => void;
|
|
37
|
+
/** Speech state changed. */
|
|
38
|
+
speechStateChanged: (state: SpeechState) => void;
|
|
39
|
+
/** Turn started or ended. */
|
|
40
|
+
turnChanged: (active: boolean) => void;
|
|
41
|
+
/** Queue was drained after turn end. */
|
|
42
|
+
queueDrained: () => void;
|
|
43
|
+
}
|
|
44
|
+
export interface VADConfig {
|
|
45
|
+
/** RMS amplitude threshold (0-1). Default: 0.01 */
|
|
46
|
+
threshold?: number;
|
|
47
|
+
/** Analysis interval in ms. Default: 50 */
|
|
48
|
+
analyseIntervalMs?: number;
|
|
49
|
+
/** Consecutive frames above threshold to trigger speech start. Default: 3 (~150ms) */
|
|
50
|
+
speechStartFrames?: number;
|
|
51
|
+
/** Consecutive frames below threshold to trigger speech pause (visual only). Default: 8 (~400ms) */
|
|
52
|
+
speechPauseFrames?: number;
|
|
53
|
+
/** Consecutive frames below threshold to trigger turn end (queue drains). Default: 16 (~800ms) */
|
|
54
|
+
turnEndFrames?: number;
|
|
55
|
+
/** FFT size for the analyser node. Default: 256 */
|
|
56
|
+
fftSize?: number;
|
|
57
|
+
}
|
|
58
|
+
export interface VADEvents {
|
|
59
|
+
/** Speech started (above threshold for speechStartFrames). */
|
|
60
|
+
speechStart: () => void;
|
|
61
|
+
/** Speech paused (below threshold for speechPauseFrames, but turn still active). */
|
|
62
|
+
speechPause: () => void;
|
|
63
|
+
/** Speech resumed after a pause within the same turn. */
|
|
64
|
+
speechResume: () => void;
|
|
65
|
+
/** Turn ended (below threshold for turnEndFrames). */
|
|
66
|
+
turnEnd: () => void;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAExD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,CAAC;CAClB;AAID,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,SAAS,GACT,OAAO,GACP,OAAO,CAAC;AAIZ,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,OAAO,EAAE,GAAG,CAAC;IACb,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAID,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,4CAA4C;IAC5C,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,+CAA+C;IAC/C,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,6CAA6C;IAC7C,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,yBAAyB;IACzB,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC9B,8BAA8B;IAC9B,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC9C;AAID,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,iBAAiB;IAChC,4CAA4C;IAC5C,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D,4BAA4B;IAC5B,kBAAkB,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACjD,6BAA6B;IAC7B,WAAW,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,wCAAwC;IACxC,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B;AAID,MAAM,WAAW,SAAS;IACxB,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sFAAsF;IACtF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oGAAoG;IACpG,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kGAAkG;IAClG,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,oFAAoF;IACpF,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,yDAAyD;IACzD,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,sDAAsD;IACtD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB"}
|