@spatius/avatarkit 0.5.0 → 1.0.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/CHANGELOG.md +9 -16
- package/README.md +6 -17
- package/dist/{StreamingAudioPlayer-D-7zAYjb.js → StreamingAudioPlayer-Cq5jTVny.js} +1 -1
- package/dist/core/Avatar.d.ts +1 -0
- package/dist/core/AvatarController.d.ts +13 -17
- package/dist/core/AvatarSDK.d.ts +0 -1
- package/dist/core/AvatarView.d.ts +58 -12
- package/dist/{index-DrRoews_.js → index-zTpDp_Pv.js} +6931 -6700
- package/dist/index.js +7 -5
- package/dist/types/character.d.ts +2 -0
- package/dist/types/index.d.ts +11 -2
- package/package.json +1 -1
- package/dist/performance/FrameRateMonitor.d.ts +0 -85
package/CHANGELOG.md
CHANGED
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
- Real-time 3D avatar rendering powered by WebGL/WebGPU + WASM.
|
|
9
|
-
- Streaming audio-driven animation with low-latency lip sync.
|
|
10
|
-
- SDK mode and host mode for the driving service.
|
|
11
|
-
- Animation state callbacks (idle, speaking, fallback transitions).
|
|
12
|
-
- Telemetry built in (PostHog).
|
|
13
|
-
- Vite and Next.js plugins for zero-config WASM asset handling.
|
|
8
|
+
## [1.0.0] - 2026-05-17
|
|
14
9
|
|
|
15
|
-
|
|
16
|
-
- `AvatarSDK` – SDK lifecycle, configuration, session token, device support.
|
|
17
|
-
- `AvatarManager` – avatar resource loading and caching.
|
|
18
|
-
- `Avatar` / `AvatarView` / `AvatarController` – rendering and conversation control.
|
|
19
|
-
- Types: `Configuration`, `AudioFormat`, `ConnectionState`, `ConversationState`, `DrivingServiceMode`, `LogLevel`, `LoadProgressInfo`, `CameraConfig`, `PostProcessingConfig`, `AvatarError`.
|
|
10
|
+
First stable release.
|
|
20
11
|
|
|
21
|
-
|
|
22
|
-
-
|
|
12
|
+
- Real-time avatar rendering with WebGL and WebGPU backends.
|
|
13
|
+
- Audio-driven SDK mode and host-driven mode for custom animation pipelines.
|
|
14
|
+
- Public API: `AvatarSDK`, `AvatarView`, `AvatarController`, `AvatarManager`.
|
|
15
|
+
- See [README.md](README.md) for installation and usage.
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @spatius/avatarkit
|
|
2
2
|
|
|
3
3
|
Real-time virtual avatar rendering SDK for Web, supporting audio-driven animation and high-quality 3D rendering.
|
|
4
4
|
|
|
@@ -165,7 +165,7 @@ All environments require an **App ID** and **Session Token** for authentication.
|
|
|
165
165
|
The App ID is used to identify your application. You can obtain your App ID by:
|
|
166
166
|
|
|
167
167
|
1. **For Testing**: Use the default test App ID provided in demo repositories (paired with test Session Token, only works with publicly available test avatars like Rohan, Dr.Kellan, Priya, Josh, etc.)
|
|
168
|
-
2. **For Production**: Visit the [Developer Platform](https://
|
|
168
|
+
2. **For Production**: Visit the [Developer Platform](https://app.spatius.ai) to create your own App and avatars. You will receive your own App ID after creating an App.
|
|
169
169
|
|
|
170
170
|
### Session Token
|
|
171
171
|
|
|
@@ -175,7 +175,7 @@ The Session Token is required for authentication and must be obtained from your
|
|
|
175
175
|
- The Session Token must be valid and not expired
|
|
176
176
|
- In production applications, you **must** manually inject a valid Session Token obtained from your SDK provider
|
|
177
177
|
- The default Session Token provided in demo repositories is **only for demonstration purposes** and can only be used with test avatars
|
|
178
|
-
- If you want to create your own avatars and test them, please visit the [Developer Platform](https://
|
|
178
|
+
- If you want to create your own avatars and test them, please visit the [Developer Platform](https://app.spatius.ai) to create your own App and generate Session Tokens
|
|
179
179
|
|
|
180
180
|
**How to Set Session Token:**
|
|
181
181
|
|
|
@@ -237,7 +237,6 @@ const configuration: Configuration = {
|
|
|
237
237
|
sampleRate: 16000 // Supported: 8000, 16000, 22050, 24000, 32000, 44100, 48000 Hz
|
|
238
238
|
// ⚠️ Must match your actual audio sample rate. Mismatched sample rate will cause playback issues.
|
|
239
239
|
}
|
|
240
|
-
// characterApiBaseUrl: 'https://custom-api.example.com' // Optional, internal debug config, can be ignored
|
|
241
240
|
}
|
|
242
241
|
|
|
243
242
|
await AvatarSDK.initialize('your-app-id', configuration)
|
|
@@ -690,7 +689,6 @@ button.addEventListener('click', async () => {
|
|
|
690
689
|
- `yieldAudioData()` returns a conversationId (automatically generates if starting new session)
|
|
691
690
|
- `yieldFramesData()` requires a valid conversationId parameter
|
|
692
691
|
- Animation data with mismatched conversationId will be **discarded**
|
|
693
|
-
- Use `getCurrentConversationId()` to retrieve the current active conversationId
|
|
694
692
|
|
|
695
693
|
#### Common Methods (Both Modes)
|
|
696
694
|
|
|
@@ -705,13 +703,6 @@ await avatarView.controller.resume()
|
|
|
705
703
|
// Interrupt current playback (stops and clears data)
|
|
706
704
|
avatarView.controller.interrupt()
|
|
707
705
|
|
|
708
|
-
// Clear all data and resources
|
|
709
|
-
avatarView.controller.clear()
|
|
710
|
-
|
|
711
|
-
// Get current conversation ID (for Host mode)
|
|
712
|
-
const conversationId = avatarView.controller.getCurrentConversationId()
|
|
713
|
-
// Returns: Current conversationId for the active audio session, or null if no active session
|
|
714
|
-
|
|
715
706
|
// Volume control (affects only avatar audio player, not system volume)
|
|
716
707
|
avatarView.controller.setVolume(0.5) // Set volume to 50% (0.0 to 1.0)
|
|
717
708
|
const currentVolume = avatarView.controller.getVolume() // Get current volume (0.0 to 1.0)
|
|
@@ -742,7 +733,7 @@ avatarView.avatarTransform = { x: 0.5, y: 0, scale: 2.0 } // Right half, double
|
|
|
742
733
|
**Important Notes:**
|
|
743
734
|
- `start()` and `close()` are only available in SDK mode
|
|
744
735
|
- `yieldAudioData()` and `yieldFramesData()` are only available in Host mode
|
|
745
|
-
- `pause()`, `resume()`, `interrupt()`, `
|
|
736
|
+
- `pause()`, `resume()`, `interrupt()`, `setVolume()`, and `getVolume()` are available in both modes
|
|
746
737
|
- The playback mode is determined when creating `AvatarView` and cannot be changed
|
|
747
738
|
|
|
748
739
|
## 🔧 Configuration
|
|
@@ -754,7 +745,6 @@ interface Configuration {
|
|
|
754
745
|
drivingServiceMode?: DrivingServiceMode // Optional, default is 'sdk' (SDK mode)
|
|
755
746
|
logLevel?: LogLevel // Optional, default is 'off' (no logs)
|
|
756
747
|
audioFormat?: AudioFormat // Optional, default is { channelCount: 1, sampleRate: 16000 }
|
|
757
|
-
characterApiBaseUrl?: string // Optional, internal debug config, can be ignored
|
|
758
748
|
}
|
|
759
749
|
|
|
760
750
|
interface AudioFormat {
|
|
@@ -792,7 +782,6 @@ enum LogLevel {
|
|
|
792
782
|
- `sampleRate`: Audio sample rate in Hz (default: 16000)
|
|
793
783
|
- Supported values: 8000, 16000, 22050, 24000, 32000, 44100, 48000
|
|
794
784
|
- The configured sample rate will be used for both audio recording and playback
|
|
795
|
-
- `characterApiBaseUrl`: Internal debug config, can be ignored
|
|
796
785
|
- `sessionToken`: **Required for authentication**. Set separately via `AvatarSDK.setSessionToken()`, not in Configuration. See [Authentication](#-authentication) section for details
|
|
797
786
|
|
|
798
787
|
### CameraConfig
|
|
@@ -947,7 +936,7 @@ avatarView.dispose()
|
|
|
947
936
|
- Render system and canvas elements
|
|
948
937
|
- All event listeners and callbacks
|
|
949
938
|
- Not properly calling `dispose()` may cause resource leaks and rendering errors
|
|
950
|
-
- If you need to manually close connections
|
|
939
|
+
- If you need to manually close connections before disposing, you can call `avatarView.controller.close()` (SDK mode) first, but it's not required as `dispose()` handles this automatically
|
|
951
940
|
|
|
952
941
|
### Memory Optimization
|
|
953
942
|
|
|
@@ -973,4 +962,4 @@ Issues and Pull Requests are welcome!
|
|
|
973
962
|
|
|
974
963
|
For questions, please contact:
|
|
975
964
|
- Email: code@spatius.net
|
|
976
|
-
- Documentation: https://docs.
|
|
965
|
+
- Documentation: https://docs.spatius.ai
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import { A as APP_CONFIG, l as logger, e as errorToMessage, a as logEvent } from "./index-
|
|
4
|
+
import { A as APP_CONFIG, l as logger, e as errorToMessage, a as logEvent } from "./index-zTpDp_Pv.js";
|
|
5
5
|
class StreamingAudioPlayer {
|
|
6
6
|
// Mark if AudioContext is being resumed, avoid concurrent resume requests
|
|
7
7
|
constructor(options) {
|
package/dist/core/Avatar.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Avatar } from './Avatar';
|
|
2
|
-
import { ConnectionState, AvatarError, DrivingServiceMode, ConversationState, PostProcessingConfig } from '../types';
|
|
2
|
+
import { ConnectionState, AvatarError, DrivingServiceMode, ConversationState, AnimationType, PostProcessingConfig } from '../types';
|
|
3
3
|
import { FrameRateInfo } from '../performance/FrameRateMonitor';
|
|
4
4
|
export declare class AvatarController {
|
|
5
5
|
private networkLayer?;
|
|
@@ -10,6 +10,8 @@ export declare class AvatarController {
|
|
|
10
10
|
onConnectionState: ((state: ConnectionState) => void) | null;
|
|
11
11
|
onConversationState: ((state: ConversationState) => void) | null;
|
|
12
12
|
onError: ((error: AvatarError) => void) | null;
|
|
13
|
+
/** Callback for animation type changes (e.g., idle → mono in fallback mode). Aligned with iOS/Android AvatarController.onAnimationState. */
|
|
14
|
+
onAnimationState: ((type: AnimationType) => void) | null;
|
|
13
15
|
private eventListeners;
|
|
14
16
|
private readonly frameRateMonitor;
|
|
15
17
|
/** Frame rate monitoring callback. Fires with aggregated metrics from a 2-second sliding window. */
|
|
@@ -22,8 +24,7 @@ export declare class AvatarController {
|
|
|
22
24
|
private characterHandle;
|
|
23
25
|
private characterId;
|
|
24
26
|
private postProcessingConfig;
|
|
25
|
-
private
|
|
26
|
-
private playbackLoopGeneration;
|
|
27
|
+
private audioMonitorLoopId;
|
|
27
28
|
private lastRenderedFrameIndex;
|
|
28
29
|
private keyframesOffset;
|
|
29
30
|
private readonly MAX_KEYFRAMES;
|
|
@@ -43,14 +44,13 @@ export declare class AvatarController {
|
|
|
43
44
|
playbackMode?: DrivingServiceMode;
|
|
44
45
|
});
|
|
45
46
|
private handleVisibilityChange;
|
|
46
|
-
private shouldReportPlaybackStats;
|
|
47
|
-
private _getDeviceScoreProps;
|
|
48
47
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* @returns Current conversation ID, or null if no active session
|
|
48
|
+
* Playback time of the current audio session, in seconds.
|
|
49
|
+
* Resets to 0 on each new playback round. Returns 0 when not playing.
|
|
52
50
|
*/
|
|
53
|
-
|
|
51
|
+
getAudioTime(): number;
|
|
52
|
+
private shouldReportPlaybackStats;
|
|
53
|
+
private _getDeviceScoreProps;
|
|
54
54
|
/**
|
|
55
55
|
* Initialize audio context (must be called in user gesture context)
|
|
56
56
|
*
|
|
@@ -92,7 +92,7 @@ export declare class AvatarController {
|
|
|
92
92
|
* Public API: accepts binary data array (protobuf encoded Message array)
|
|
93
93
|
* @param keyframesDataArray - Animation keyframes binary data array (each element is a protobuf encoded Message) or empty array to trigger audio-only mode
|
|
94
94
|
* @param conversationId - Conversation ID (required). If conversationId doesn't match current conversationId, keyframes will be discarded.
|
|
95
|
-
*
|
|
95
|
+
* The conversationId is returned by yieldAudioData().
|
|
96
96
|
* @returns `true` if the server has sent all animation data for this conversation (end signal received), `false` otherwise.
|
|
97
97
|
*/
|
|
98
98
|
yieldFramesData(keyframesDataArray: (Uint8Array | ArrayBuffer)[], conversationId: string): boolean;
|
|
@@ -112,14 +112,9 @@ export declare class AvatarController {
|
|
|
112
112
|
*/
|
|
113
113
|
interrupt(): void;
|
|
114
114
|
/**
|
|
115
|
-
*
|
|
116
|
-
*/
|
|
117
|
-
clear(): void;
|
|
118
|
-
/**
|
|
119
|
-
* Get point cloud count of the current avatar
|
|
120
|
-
* @returns Point cloud count, or null if avatar is not loaded
|
|
115
|
+
* The point count of current avatar, or null if avatar is not loaded.
|
|
121
116
|
*/
|
|
122
|
-
|
|
117
|
+
get pointCount(): number | null;
|
|
123
118
|
/**
|
|
124
119
|
* Set post-processing configuration
|
|
125
120
|
* These parameters will be applied in real-time to animation parameters returned by the server
|
|
@@ -137,4 +132,5 @@ export declare class AvatarController {
|
|
|
137
132
|
* @returns Current volume value (0.0 - 1.0)
|
|
138
133
|
*/
|
|
139
134
|
getVolume(): number;
|
|
135
|
+
protected stopPlayback(): void;
|
|
140
136
|
}
|
package/dist/core/AvatarSDK.d.ts
CHANGED
|
@@ -25,7 +25,6 @@ export declare class AvatarSDK {
|
|
|
25
25
|
* Optional interface for developers, SDK includes this in telemetry logs
|
|
26
26
|
*/
|
|
27
27
|
static setUserId(userId: string): void;
|
|
28
|
-
static get isInitialized(): boolean;
|
|
29
28
|
static get appId(): string | null;
|
|
30
29
|
static get configuration(): Configuration | null;
|
|
31
30
|
static get sessionToken(): string | null;
|
|
@@ -9,26 +9,23 @@ export declare class AvatarView {
|
|
|
9
9
|
private renderSystem;
|
|
10
10
|
private isInitialized;
|
|
11
11
|
private cameraConfig;
|
|
12
|
-
private
|
|
13
|
-
private currentKeyframes;
|
|
14
|
-
private lastRenderedFrameIndex;
|
|
15
|
-
private lastRealtimeProtoFrame;
|
|
16
|
-
private idleAnimationLoopId;
|
|
17
|
-
private realtimeAnimationLoopId;
|
|
12
|
+
private renderLoopId;
|
|
18
13
|
private resizeObserver;
|
|
19
14
|
private onWindowResize;
|
|
15
|
+
private onVisibilityChange;
|
|
20
16
|
private frameCount;
|
|
21
17
|
private lastFpsUpdate;
|
|
22
18
|
private currentFPS;
|
|
23
|
-
private transitionKeyframes;
|
|
24
|
-
private transitionStartTime;
|
|
25
|
-
private readonly startTransitionDurationMs;
|
|
26
|
-
private readonly endTransitionDurationMs;
|
|
27
|
-
private cachedIdleFirstFrame;
|
|
28
|
-
private idleCurrentFrameIndex;
|
|
29
19
|
private currentPlayingFrame;
|
|
20
|
+
private cachedIdleFirstFrame;
|
|
30
21
|
private characterHandle;
|
|
31
22
|
private characterId;
|
|
23
|
+
private transitionFrames;
|
|
24
|
+
private onTransitionFramesConsumed;
|
|
25
|
+
private isConversationActive;
|
|
26
|
+
private lastRenderedFrameIndex;
|
|
27
|
+
private animationHandleMap;
|
|
28
|
+
private activeAnimationState;
|
|
32
29
|
private isPureRenderingMode;
|
|
33
30
|
private _renderingEnabled;
|
|
34
31
|
private avatarActiveTimer;
|
|
@@ -44,6 +41,28 @@ export declare class AvatarView {
|
|
|
44
41
|
* Get controller (public interface)
|
|
45
42
|
*/
|
|
46
43
|
get controller(): AvatarController;
|
|
44
|
+
private _exportBitmapResolve;
|
|
45
|
+
/**
|
|
46
|
+
* Exports the current rendering as a Blob (PNG).
|
|
47
|
+
* Returns null if the canvas is not initialized or not rendering.
|
|
48
|
+
* Aligned with iOS exportBitmap() / Android exportBitmap().
|
|
49
|
+
*
|
|
50
|
+
* The capture happens synchronously inside the render loop (after renderFrame)
|
|
51
|
+
* to work correctly with WebGL preserveDrawingBuffer:false.
|
|
52
|
+
*/
|
|
53
|
+
exportBitmap(): Promise<Blob | null>;
|
|
54
|
+
/** @deprecated Use startRenderLoop() */
|
|
55
|
+
private startIdleAnimationLoop;
|
|
56
|
+
/**
|
|
57
|
+
* Render a specific idle frame by index for benchmark capture.
|
|
58
|
+
* Bypasses animation loop and _renderingEnabled check.
|
|
59
|
+
*/
|
|
60
|
+
renderIdleFrameForBenchmark(frameIndex: number): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Render a single frame from FlameParams for benchmark capture (transition / speaking).
|
|
63
|
+
* Bypasses animation loop and _renderingEnabled check.
|
|
64
|
+
*/
|
|
65
|
+
renderFrameForBenchmark(flameParams: import('../wasm/avatarCoreAdapter').FlameParams): Promise<void>;
|
|
47
66
|
/**
|
|
48
67
|
* Cleanup view resources
|
|
49
68
|
* Closes avatarController and cleans up all related resources
|
|
@@ -167,4 +186,31 @@ export declare class AvatarView {
|
|
|
167
186
|
y: number;
|
|
168
187
|
scale: number;
|
|
169
188
|
});
|
|
189
|
+
/**
|
|
190
|
+
* Get the approximate bounding rectangle of the avatar in canvas pixel coordinates.
|
|
191
|
+
* Projects idle first frame positions through current view/projection matrices and transform.
|
|
192
|
+
* No caching is performed — each call recomputes from scratch.
|
|
193
|
+
*
|
|
194
|
+
* **Important:** The result depends on the current canvas size and `avatarTransform`.
|
|
195
|
+
* You must call this method again after any of the following changes to get an up-to-date result:
|
|
196
|
+
* - Canvas / container size changes (e.g. window resize)
|
|
197
|
+
* - `avatarTransform` changes (offset or scale)
|
|
198
|
+
*
|
|
199
|
+
* **Performance note:** Each call iterates ~70k splat points. Avoid calling every frame;
|
|
200
|
+
* call on-demand (e.g. after init, on resize, after transform change).
|
|
201
|
+
*
|
|
202
|
+
* @returns Bounding rectangle { x, y, width, height } in CSS pixels (top-left origin), or null if not ready
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* const rect = avatarView.getBoundingRect()
|
|
206
|
+
* if (rect) {
|
|
207
|
+
* console.log(`Avatar at (${rect.x}, ${rect.y}), size ${rect.width}x${rect.height}`)
|
|
208
|
+
* }
|
|
209
|
+
*/
|
|
210
|
+
getBoundingRect(): {
|
|
211
|
+
x: number;
|
|
212
|
+
y: number;
|
|
213
|
+
width: number;
|
|
214
|
+
height: number;
|
|
215
|
+
} | null;
|
|
170
216
|
}
|