@spatialwalk/avatarkit 1.0.0-beta.1 → 1.0.0-beta.11

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.
Files changed (67) hide show
  1. package/CHANGELOG.md +185 -0
  2. package/README.md +450 -148
  3. package/dist/{StreamingAudioPlayer-C2TfYsO8.js → StreamingAudioPlayer-CLFmPod8.js} +88 -62
  4. package/dist/StreamingAudioPlayer-CLFmPod8.js.map +1 -0
  5. package/dist/animation/AnimationWebSocketClient.d.ts.map +1 -1
  6. package/dist/animation/utils/flameConverter.d.ts.map +1 -1
  7. package/dist/audio/AnimationPlayer.d.ts +4 -0
  8. package/dist/audio/AnimationPlayer.d.ts.map +1 -1
  9. package/dist/audio/StreamingAudioPlayer.d.ts +10 -0
  10. package/dist/audio/StreamingAudioPlayer.d.ts.map +1 -1
  11. package/dist/avatar_core_wasm-D4eEi7Eh.js +1666 -0
  12. package/dist/{avatar_core_wasm-DmkU6dYn.js.map → avatar_core_wasm-D4eEi7Eh.js.map} +1 -1
  13. package/dist/avatar_core_wasm.wasm +0 -0
  14. package/dist/config/app-config.d.ts +3 -7
  15. package/dist/config/app-config.d.ts.map +1 -1
  16. package/dist/config/constants.d.ts +19 -3
  17. package/dist/config/constants.d.ts.map +1 -1
  18. package/dist/core/Avatar.d.ts +0 -8
  19. package/dist/core/Avatar.d.ts.map +1 -1
  20. package/dist/core/AvatarController.d.ts +50 -74
  21. package/dist/core/AvatarController.d.ts.map +1 -1
  22. package/dist/core/AvatarDownloader.d.ts +0 -5
  23. package/dist/core/AvatarDownloader.d.ts.map +1 -1
  24. package/dist/core/AvatarKit.d.ts +3 -15
  25. package/dist/core/AvatarKit.d.ts.map +1 -1
  26. package/dist/core/AvatarManager.d.ts.map +1 -1
  27. package/dist/core/AvatarView.d.ts +47 -46
  28. package/dist/core/AvatarView.d.ts.map +1 -1
  29. package/dist/core/NetworkLayer.d.ts +59 -0
  30. package/dist/core/NetworkLayer.d.ts.map +1 -0
  31. package/dist/index-Ck21a9C4.js +5999 -0
  32. package/dist/index-Ck21a9C4.js.map +1 -0
  33. package/dist/index.d.ts +0 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +11 -11
  36. package/dist/renderer/RenderSystem.d.ts +4 -2
  37. package/dist/renderer/RenderSystem.d.ts.map +1 -1
  38. package/dist/renderer/webgl/webglRenderer.d.ts.map +1 -1
  39. package/dist/types/index.d.ts +18 -0
  40. package/dist/types/index.d.ts.map +1 -1
  41. package/dist/utils/cls-tracker.d.ts +17 -0
  42. package/dist/utils/cls-tracker.d.ts.map +1 -0
  43. package/dist/utils/logger.d.ts +1 -1
  44. package/dist/utils/logger.d.ts.map +1 -1
  45. package/package.json +14 -18
  46. package/dist/StreamingAudioPlayer-C2TfYsO8.js.map +0 -1
  47. package/dist/avatar_core_wasm-DmkU6dYn.js +0 -1666
  48. package/dist/config/region-config.d.ts +0 -17
  49. package/dist/config/region-config.d.ts.map +0 -1
  50. package/dist/generated/google/protobuf/any.d.ts +0 -145
  51. package/dist/generated/google/protobuf/any.d.ts.map +0 -1
  52. package/dist/generated/jsonapi/v1/base.d.ts +0 -140
  53. package/dist/generated/jsonapi/v1/base.d.ts.map +0 -1
  54. package/dist/generated/platform/v1/asset_groups.d.ts +0 -225
  55. package/dist/generated/platform/v1/asset_groups.d.ts.map +0 -1
  56. package/dist/generated/platform/v1/assets.d.ts +0 -149
  57. package/dist/generated/platform/v1/assets.d.ts.map +0 -1
  58. package/dist/generated/platform/v1/character.d.ts +0 -395
  59. package/dist/generated/platform/v1/character.d.ts.map +0 -1
  60. package/dist/generated/platform/v1/redeem.d.ts +0 -22
  61. package/dist/generated/platform/v1/redeem.d.ts.map +0 -1
  62. package/dist/index-DwhR9l52.js +0 -9712
  63. package/dist/index-DwhR9l52.js.map +0 -1
  64. package/dist/utils/posthog-tracker.d.ts +0 -82
  65. package/dist/utils/posthog-tracker.d.ts.map +0 -1
  66. package/dist/utils/toast.d.ts +0 -74
  67. package/dist/utils/toast.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,25 +1,25 @@
1
1
  # SPAvatarKit SDK
2
2
 
3
- 基于 3D Gaussian Splatting 的实时虚拟人物头像渲染 SDK,支持音频驱动的动画渲染和高质量 3D 渲染。
3
+ Real-time virtual avatar rendering SDK based on 3D Gaussian Splatting, supporting audio-driven animation rendering and high-quality 3D rendering.
4
4
 
5
- ## 🚀 特性
5
+ ## 🚀 Features
6
6
 
7
- - **3D Gaussian Splatting 渲染** - 基于最新的点云渲染技术,提供高质量的 3D 虚拟人物
8
- - **音频驱动的实时动画渲染** - 用户提供音频数据,SDK 负责接收动画数据并渲染
9
- - **WebGPU/WebGL 双渲染后端** - 自动选择最佳渲染后端,确保兼容性
10
- - **WASM 高性能计算** - 使用 C++ 编译的 WebAssembly 模块进行几何计算
11
- - **TypeScript 支持** - 完整的类型定义和智能提示
12
- - **模块化架构** - 清晰的组件分离,易于集成和扩展
7
+ - **3D Gaussian Splatting Rendering** - Based on the latest point cloud rendering technology, providing high-quality 3D virtual avatars
8
+ - **Audio-Driven Real-Time Animation Rendering** - Users provide audio data, SDK handles receiving animation data and rendering
9
+ - **WebGPU/WebGL Dual Rendering Backend** - Automatically selects the best rendering backend for compatibility
10
+ - **WASM High-Performance Computing** - Uses C++ compiled WebAssembly modules for geometric calculations
11
+ - **TypeScript Support** - Complete type definitions and IntelliSense
12
+ - **Modular Architecture** - Clear component separation, easy to integrate and extend
13
13
 
14
- ## 📦 安装
14
+ ## 📦 Installation
15
15
 
16
16
  ```bash
17
17
  npm install @spatialwalk/avatarkit
18
18
  ```
19
19
 
20
- ## 🎯 快速开始
20
+ ## 🎯 Quick Start
21
21
 
22
- ### 基础使用
22
+ ### Basic Usage
23
23
 
24
24
  ```typescript
25
25
  import {
@@ -30,150 +30,359 @@ import {
30
30
  Environment
31
31
  } from '@spatialwalk/avatarkit'
32
32
 
33
- // 1. 初始化 SDK
33
+ // 1. Initialize SDK
34
34
  const configuration: Configuration = {
35
35
  environment: Environment.test,
36
36
  }
37
37
 
38
38
  await AvatarKit.initialize('your-app-id', configuration)
39
39
 
40
- // 设置 sessionToken(如果需要,单独调用)
40
+ // Set sessionToken (if needed, call separately)
41
41
  // AvatarKit.setSessionToken('your-session-token')
42
42
 
43
- // 2. 加载角色
43
+ // 2. Load character
44
44
  const avatarManager = new AvatarManager()
45
45
  const avatar = await avatarManager.load('character-id', (progress) => {
46
46
  console.log(`Loading progress: ${progress.progress}%`)
47
47
  })
48
48
 
49
- // 3. 创建视图(自动创建 Canvas AvatarController
49
+ // 3. Create view (automatically creates Canvas and AvatarController)
50
+ // Network mode (default)
50
51
  const container = document.getElementById('avatar-container')
51
- const avatarView = new AvatarView(avatar, container)
52
+ const avatarView = new AvatarView(avatar, {
53
+ container: container,
54
+ playbackMode: 'network' // Optional, 'network' is default
55
+ })
52
56
 
53
- // 4. 启动实时通信
57
+ // 4. Start real-time communication (network mode only)
54
58
  await avatarView.avatarController.start()
55
59
 
56
- // 5. 发送音频数据
57
- // 如果音频是 Uint8Array,可以使用 slice().buffer 转换为 ArrayBuffer
58
- const audioUint8 = new Uint8Array(1024) // 示例:音频数据
59
- const audioData = audioUint8.slice().buffer // 简化的转换方式,适用于 ArrayBuffer SharedArrayBuffer
60
- avatarView.avatarController.send(audioData, false) // 发送音频数据,积累到一定量后会自动开始播放
61
- avatarView.avatarController.send(audioData, true) // end=true 表示立即返回动画数据,不再积累
60
+ // 5. Send audio data (network mode)
61
+ // ⚠️ Important: Audio must be 16kHz mono PCM16 format
62
+ // If audio is Uint8Array, you can use slice().buffer to convert to ArrayBuffer
63
+ const audioUint8 = new Uint8Array(1024) // Example: 16kHz PCM16 audio data (512 samples = 1024 bytes)
64
+ const audioData = audioUint8.slice().buffer // Simplified conversion, works for ArrayBuffer and SharedArrayBuffer
65
+ avatarView.avatarController.send(audioData, false) // Send audio data, will automatically start playing after accumulating enough data
66
+ avatarView.avatarController.send(audioData, true) // end=true means immediately return animation data, no longer accumulating
62
67
  ```
63
68
 
64
- ### 完整示例
69
+ ### External Data Mode Example
70
+
71
+ ```typescript
72
+ import { AvatarPlaybackMode } from '@spatialwalk/avatarkit'
73
+
74
+ // 1-3. Same as network mode (initialize SDK, load character)
75
+
76
+ // 3. Create view with external data mode
77
+ const container = document.getElementById('avatar-container')
78
+ const avatarView = new AvatarView(avatar, {
79
+ container: container,
80
+ playbackMode: AvatarPlaybackMode.external
81
+ })
82
+
83
+ // 4. Start playback with initial data (obtained from your service)
84
+ // Note: Audio and animation data should be obtained from your backend service
85
+ const initialAudioChunks = [{ data: audioData1, isLast: false }, { data: audioData2, isLast: false }]
86
+ const initialKeyframes = animationData1 // Animation keyframes from your service
87
+
88
+ await avatarView.avatarController.play(initialAudioChunks, initialKeyframes)
89
+
90
+ // 5. Stream additional data as needed
91
+ avatarView.avatarController.sendAudioChunk(audioData3, false)
92
+ avatarView.avatarController.sendKeyframes(animationData2)
93
+ ```
94
+
95
+ ### Complete Examples
96
+
97
+ Check the example code in the GitHub repository for complete usage flows for both modes.
65
98
 
66
- 查看 GitHub 仓库中的示例代码了解完整的使用流程。
99
+ **Example Project:** [AvatarKit-Web-Demo](https://github.com/spatialwalk/AvatarKit-Web-Demo)
67
100
 
68
- ## 🏗️ 架构概览
101
+ This repository contains complete examples for Vanilla JS, Vue 3, and React, demonstrating:
102
+ - Network mode: Real-time audio input with automatic animation data reception
103
+ - External data mode: Custom data sources with manual audio/animation data management
69
104
 
70
- ### 核心组件
105
+ ## 🏗️ Architecture Overview
71
106
 
72
- - **AvatarKit** - SDK 初始化和管理
73
- - **AvatarManager** - 角色资源加载和管理
74
- - **AvatarView** - 3D 渲染视图(内部包含 AvatarController)
75
- - **AvatarController** - 实时通信和数据处理
76
- - **AvatarCoreAdapter** - WASM 模块适配器
107
+ ### Three-Layer Architecture
108
+
109
+ The SDK uses a three-layer architecture for clear separation of concerns:
110
+
111
+ 1. **Rendering Layer (AvatarView)** - Responsible for 3D rendering only
112
+ 2. **Playback Layer (AvatarController)** - Manages audio/animation synchronization and playback
113
+ 3. **Network Layer (NetworkLayer)** - Handles WebSocket communication (only in network mode)
114
+
115
+ ### Core Components
116
+
117
+ - **AvatarKit** - SDK initialization and management
118
+ - **AvatarManager** - Character resource loading and management
119
+ - **AvatarView** - 3D rendering view (rendering layer)
120
+ - **AvatarController** - Audio/animation playback controller (playback layer)
121
+ - **NetworkLayer** - WebSocket communication (network layer, automatically composed in network mode)
122
+ - **AvatarCoreAdapter** - WASM module adapter
123
+
124
+ ### Playback Modes
125
+
126
+ The SDK supports two playback modes, configured when creating `AvatarView`:
127
+
128
+ #### 1. Network Mode (Default)
129
+ - SDK handles WebSocket communication automatically
130
+ - Send audio data via `AvatarController.send()`
131
+ - SDK receives animation data from backend and synchronizes playback
132
+ - Best for: Real-time audio input scenarios
133
+
134
+ #### 2. External Data Mode
135
+ - External components manage their own network/data fetching
136
+ - External components provide both audio and animation data
137
+ - SDK only handles synchronized playback
138
+ - Best for: Custom data sources, pre-recorded content, or custom network implementations
139
+
140
+ ### Data Flow
141
+
142
+ #### Network Mode Flow
143
+
144
+ ```
145
+ User audio input (16kHz mono PCM16)
146
+
147
+ AvatarController.send()
148
+
149
+ NetworkLayer → WebSocket → Backend processing
150
+
151
+ Backend returns animation data (FLAME keyframes)
152
+
153
+ NetworkLayer → AvatarController → AnimationPlayer
154
+
155
+ FLAME parameters → AvatarCore.computeFrameFlatFromParams() → Splat data
156
+
157
+ AvatarController (playback loop) → AvatarView.renderRealtimeFrame()
158
+
159
+ RenderSystem → WebGPU/WebGL → Canvas rendering
160
+ ```
77
161
 
78
- ### 数据流
162
+ #### External Data Mode Flow
79
163
 
80
164
  ```
81
- 用户音频输入(16kHz mono PCM) AvatarController → WebSocket → 后台处理
82
-
83
- 后台返回动画数据(FLAME 关键帧) AvatarController → AnimationPlayer
84
-
85
- FLAME 参数 → AvatarCore.computeFrameFlatFromParams() Splat 数据
86
-
87
- Splat 数据 → RenderSystem → WebGPU/WebGL → Canvas 渲染
165
+ External data source (audio + animation)
166
+
167
+ AvatarController.play(initialAudio, initialKeyframes) // Start playback
168
+
169
+ AvatarController.sendAudioChunk() // Stream additional audio
170
+ AvatarController.sendKeyframes() // Stream additional animation
171
+
172
+ AvatarController → AnimationPlayer (synchronized playback)
173
+
174
+ FLAME parameters → AvatarCore.computeFrameFlatFromParams() → Splat data
175
+
176
+ AvatarController (playback loop) → AvatarView.renderRealtimeFrame()
177
+
178
+ RenderSystem → WebGPU/WebGL → Canvas rendering
88
179
  ```
89
180
 
90
- **注意:** 用户需要自己提供音频数据(16kHz mono PCM),SDK 负责接收动画数据并渲染。
181
+ **Note:**
182
+ - In network mode, users provide audio data, SDK handles network communication and animation data reception
183
+ - In external data mode, users provide both audio and animation data, SDK handles synchronized playback only
91
184
 
92
- ## 📚 API 参考
185
+ ### Audio Format Requirements
186
+
187
+ **⚠️ Important:** The SDK requires audio data to be in **16kHz mono PCM16** format:
188
+
189
+ - **Sample Rate**: 16kHz (16000 Hz) - This is a backend requirement
190
+ - **Channels**: Mono (single channel)
191
+ - **Format**: PCM16 (16-bit signed integer, little-endian)
192
+ - **Byte Order**: Little-endian
193
+
194
+ **Audio Data Format:**
195
+ - Each sample is 2 bytes (16-bit)
196
+ - Audio data should be provided as `ArrayBuffer` or `Uint8Array`
197
+ - For example: 1 second of audio = 16000 samples × 2 bytes = 32000 bytes
198
+
199
+ **Resampling:**
200
+ - If your audio source is at a different sample rate (e.g., 24kHz, 48kHz), you must resample it to 16kHz before sending to the SDK
201
+ - For high-quality resampling, we recommend using Web Audio API's `OfflineAudioContext` with anti-aliasing filtering
202
+ - See example projects for resampling implementation
203
+
204
+ ## 📚 API Reference
93
205
 
94
206
  ### AvatarKit
95
207
 
96
- SDK 的核心管理类,负责初始化和全局配置。
208
+ The core management class of the SDK, responsible for initialization and global configuration.
97
209
 
98
210
  ```typescript
99
- // 初始化 SDK
211
+ // Initialize SDK
100
212
  await AvatarKit.initialize(appId: string, configuration: Configuration)
101
213
 
102
- // 检查初始化状态
214
+ // Check initialization status
103
215
  const isInitialized = AvatarKit.isInitialized
104
216
 
105
- // 清理资源(不再使用时必须调用)
217
+ // Get initialized app ID
218
+ const appId = AvatarKit.appId
219
+
220
+ // Get configuration
221
+ const config = AvatarKit.configuration
222
+
223
+ // Set sessionToken (if needed, call separately)
224
+ AvatarKit.setSessionToken('your-session-token')
225
+
226
+ // Set userId (optional, for telemetry)
227
+ AvatarKit.setUserId('user-id')
228
+
229
+ // Get sessionToken
230
+ const sessionToken = AvatarKit.sessionToken
231
+
232
+ // Get userId
233
+ const userId = AvatarKit.userId
234
+
235
+ // Get SDK version
236
+ const version = AvatarKit.version
237
+
238
+ // Cleanup resources (must be called when no longer in use)
106
239
  AvatarKit.cleanup()
107
240
  ```
108
241
 
109
242
  ### AvatarManager
110
243
 
111
- 角色资源管理器,负责下载、缓存和加载角色数据。
244
+ Character resource manager, responsible for downloading, caching, and loading character data.
112
245
 
113
246
  ```typescript
114
247
  const manager = new AvatarManager()
115
248
 
116
- // 加载角色
249
+ // Load character
117
250
  const avatar = await manager.load(
118
251
  characterId: string,
119
252
  onProgress?: (progress: LoadProgressInfo) => void
120
253
  )
121
254
 
122
- // 清理缓存
255
+ // Clear cache
123
256
  manager.clearCache()
124
257
  ```
125
258
 
126
259
  ### AvatarView
127
260
 
128
- 3D 渲染视图,内部自动创建和管理 AvatarController
261
+ 3D rendering view (rendering layer), responsible for 3D rendering only. Internally automatically creates and manages `AvatarController`.
262
+
263
+ **⚠️ Important Limitation:** Currently, the SDK only supports one AvatarView instance at a time. If you need to switch characters, you must first call the `dispose()` method to clean up the current AvatarView, then create a new instance.
264
+
265
+ **Playback Mode Configuration:**
266
+ - The playback mode is fixed when creating `AvatarView` and persists throughout its lifecycle
267
+ - Cannot be changed after creation
129
268
 
130
269
  ```typescript
131
- // 创建视图(Canvas 会自动添加到容器中)
132
- const avatarView = new AvatarView(avatar: Avatar, container?: HTMLElement)
270
+ import { AvatarPlaybackMode } from '@spatialwalk/avatarkit'
133
271
 
134
- // 获取 Canvas 元素
135
- const canvas = avatarView.getCanvas()
272
+ // Create view (Canvas is automatically added to container)
273
+ // Network mode (default)
274
+ const container = document.getElementById('avatar-container')
275
+ const avatarView = new AvatarView(avatar: Avatar, {
276
+ container: container,
277
+ playbackMode: AvatarPlaybackMode.network // Optional, default is 'network'
278
+ })
136
279
 
137
- // 设置背景
138
- avatarView.setBackgroundImage('path/to/image.jpg')
139
- avatarView.setBackgroundOpaque(true)
280
+ // External data mode
281
+ const avatarView = new AvatarView(avatar: Avatar, {
282
+ container: container,
283
+ playbackMode: AvatarPlaybackMode.external
284
+ })
140
285
 
141
- // 更新相机配置
142
- avatarView.updateCameraConfig(cameraConfig: CameraConfig)
286
+ // Get playback mode
287
+ const mode = avatarView.playbackMode // 'network' | 'external'
143
288
 
144
- // 清理资源
289
+ // Cleanup resources (must be called before switching characters)
145
290
  avatarView.dispose()
146
291
  ```
147
292
 
293
+ **Character Switching Example:**
294
+
295
+ ```typescript
296
+ // Before switching characters, must clean up old AvatarView first
297
+ if (currentAvatarView) {
298
+ currentAvatarView.dispose()
299
+ currentAvatarView = null
300
+ }
301
+
302
+ // Load new character
303
+ const newAvatar = await avatarManager.load('new-character-id')
304
+
305
+ // Create new AvatarView (with same or different playback mode)
306
+ currentAvatarView = new AvatarView(newAvatar, {
307
+ container: container,
308
+ playbackMode: AvatarPlaybackMode.network
309
+ })
310
+
311
+ // Network mode: start connection
312
+ if (currentAvatarView.playbackMode === AvatarPlaybackMode.network) {
313
+ await currentAvatarView.avatarController.start()
314
+ }
315
+ ```
316
+
148
317
  ### AvatarController
149
318
 
150
- 实时通信控制器,处理 WebSocket 连接和动画数据。
319
+ Audio/animation playback controller (playback layer), manages synchronized playback of audio and animation. Automatically composes `NetworkLayer` in network mode.
320
+
321
+ **Two Usage Patterns:**
322
+
323
+ #### Network Mode Methods
151
324
 
152
325
  ```typescript
153
- // 启动连接
326
+ // Start WebSocket service
154
327
  await avatarView.avatarController.start()
155
328
 
156
- // 发送音频数据
329
+ // Send audio data (SDK handles receiving animation data automatically)
157
330
  avatarView.avatarController.send(audioData: ArrayBuffer, end: boolean)
158
- // audioData: 音频数据(ArrayBuffer 格式)
159
- // end: false(默认)- 正常发送音频数据,服务端会积累音频数据,积累到一定量后会自动返回动画数据并开始同步播放动画和音频
160
- // end: true - 立即返回动画数据,不再积累,用于结束当前对话或需要立即响应的场景
331
+ // audioData: Audio data (ArrayBuffer format, must be 16kHz mono PCM16)
332
+ // - Sample rate: 16kHz (16000 Hz) - backend requirement
333
+ // - Format: PCM16 (16-bit signed integer, little-endian)
334
+ // - Channels: Mono (single channel)
335
+ // - Example: 1 second = 16000 samples × 2 bytes = 32000 bytes
336
+ // end: false (default) - Normal audio data sending, server will accumulate audio data, automatically returns animation data and starts synchronized playback of animation and audio after accumulating enough data
337
+ // end: true - Immediately return animation data, no longer accumulating, used for ending current conversation or scenarios requiring immediate response
338
+
339
+ // Close WebSocket service
340
+ avatarView.avatarController.close()
341
+ ```
342
+
343
+ #### External Data Mode Methods
344
+
345
+ ```typescript
346
+ // Start playback with initial audio and animation data
347
+ await avatarView.avatarController.play(
348
+ initialAudioChunks?: Array<{ data: Uint8Array, isLast: boolean }>, // Initial audio chunks (16kHz mono PCM16)
349
+ initialKeyframes?: any[] // Initial animation keyframes (obtained from your service)
350
+ )
351
+
352
+ // Stream additional audio chunks (after play() is called)
353
+ avatarView.avatarController.sendAudioChunk(
354
+ data: Uint8Array, // Audio chunk data
355
+ isLast: boolean = false // Whether this is the last chunk
356
+ )
357
+
358
+ // Stream additional animation keyframes (after play() is called)
359
+ avatarView.avatarController.sendKeyframes(
360
+ keyframes: any[] // Additional animation keyframes (obtained from your service)
361
+ )
362
+ ```
363
+
364
+ #### Common Methods (Both Modes)
161
365
 
162
- // 打断对话
366
+ ```typescript
367
+ // Interrupt current playback (stops and clears data)
163
368
  avatarView.avatarController.interrupt()
164
369
 
165
- // 关闭连接
166
- avatarView.avatarController.close()
370
+ // Clear all data and resources
371
+ avatarView.avatarController.clear()
167
372
 
168
- // 设置事件回调
169
- avatarView.avatarController.onConnectionState = (state: ConnectionState) => {}
373
+ // Set event callbacks
374
+ avatarView.avatarController.onConnectionState = (state: ConnectionState) => {} // Network mode only
170
375
  avatarView.avatarController.onAvatarState = (state: AvatarState) => {}
171
376
  avatarView.avatarController.onError = (error: Error) => {}
172
-
173
- // 注意:不支持 sendText() 方法,调用会抛出错误
174
377
  ```
175
378
 
176
- ## 🔧 配置
379
+ **Important Notes:**
380
+ - `start()` and `close()` are only available in network mode
381
+ - `play()`, `sendAudioChunk()`, and `sendKeyframes()` are only available in external data mode
382
+ - `interrupt()` and `clear()` are available in both modes
383
+ - The playback mode is determined when creating `AvatarView` and cannot be changed
384
+
385
+ ## 🔧 Configuration
177
386
 
178
387
  ### Configuration
179
388
 
@@ -183,14 +392,37 @@ interface Configuration {
183
392
  }
184
393
  ```
185
394
 
186
- **说明:**
187
- - `environment`: 指定环境(cn/us/test),SDK 会根据环境自动使用对应的 API 地址和 WebSocket 地址
188
- - `sessionToken`: 通过 `AvatarKit.setSessionToken()` 单独设置,而不是在 Configuration
395
+ **Description:**
396
+ - `environment`: Specifies the environment (cn/us/test), SDK will automatically use the corresponding API address and WebSocket address based on the environment
397
+ - `sessionToken`: Set separately via `AvatarKit.setSessionToken()`, not in Configuration
189
398
 
399
+ ```typescript
190
400
  enum Environment {
191
- cn = 'cn', // 中国区
192
- us = 'us', // 美国区
193
- test = 'test' // 测试环境
401
+ cn = 'cn', // China region
402
+ us = 'us', // US region
403
+ test = 'test' // Test environment
404
+ }
405
+ ```
406
+
407
+ ### AvatarViewOptions
408
+
409
+ ```typescript
410
+ interface AvatarViewOptions {
411
+ playbackMode?: AvatarPlaybackMode // Playback mode, default is 'network'
412
+ container?: HTMLElement // Canvas container element
413
+ }
414
+ ```
415
+
416
+ **Description:**
417
+ - `playbackMode`: Specifies the playback mode (`'network'` or `'external'`), default is `'network'`
418
+ - `'network'`: SDK handles WebSocket communication, send audio via `send()`
419
+ - `'external'`: External components provide audio and animation data, SDK handles synchronized playback
420
+ - `container`: Optional container element for Canvas, if not provided, Canvas will be created but not added to DOM
421
+
422
+ ```typescript
423
+ enum AvatarPlaybackMode {
424
+ network = 'network', // Network mode: SDK handles WebSocket communication
425
+ external = 'external' // External data mode: External provides data, SDK handles playback
194
426
  }
195
427
  ```
196
428
 
@@ -198,17 +430,17 @@ enum Environment {
198
430
 
199
431
  ```typescript
200
432
  interface CameraConfig {
201
- position: [number, number, number] // 相机位置
202
- target: [number, number, number] // 相机目标
203
- fov: number // 视野角度
204
- near: number // 近裁剪面
205
- far: number // 远裁剪面
206
- up?: [number, number, number] // 上方向
207
- aspect?: number // 宽高比
433
+ position: [number, number, number] // Camera position
434
+ target: [number, number, number] // Camera target
435
+ fov: number // Field of view angle
436
+ near: number // Near clipping plane
437
+ far: number // Far clipping plane
438
+ up?: [number, number, number] // Up direction
439
+ aspect?: number // Aspect ratio
208
440
  }
209
441
  ```
210
442
 
211
- ## 📊 状态管理
443
+ ## 📊 State Management
212
444
 
213
445
  ### ConnectionState
214
446
 
@@ -225,77 +457,77 @@ enum ConnectionState {
225
457
 
226
458
  ```typescript
227
459
  enum AvatarState {
228
- idle = 'idle', // 空闲状态,呈现呼吸态
229
- active = 'active', // 活跃中,等待可播放内容
230
- playing = 'playing' // 播放中
460
+ idle = 'idle', // Idle state, showing breathing animation
461
+ active = 'active', // Active, waiting for playable content
462
+ playing = 'playing' // Playing
231
463
  }
232
464
  ```
233
465
 
234
- ## 🎨 渲染系统
466
+ ## 🎨 Rendering System
235
467
 
236
- SDK 支持两种渲染后端:
468
+ The SDK supports two rendering backends:
237
469
 
238
- - **WebGPU** - 现代浏览器的高性能渲染
239
- - **WebGL** - 兼容性更好的传统渲染
470
+ - **WebGPU** - High-performance rendering for modern browsers
471
+ - **WebGL** - Better compatibility traditional rendering
240
472
 
241
- 渲染系统会自动选择最佳的后端,无需手动配置。
473
+ The rendering system automatically selects the best backend, no manual configuration needed.
242
474
 
243
- ## 🔍 调试和监控
475
+ ## 🔍 Debugging and Monitoring
244
476
 
245
- ### 日志系统
477
+ ### Logging System
246
478
 
247
- SDK 内置了完整的日志系统,支持不同级别的日志输出:
479
+ The SDK has a built-in complete logging system, supporting different levels of log output:
248
480
 
249
481
  ```typescript
250
482
  import { logger } from '@spatialwalk/avatarkit'
251
483
 
252
- // 设置日志级别
484
+ // Set log level
253
485
  logger.setLevel('verbose') // 'basic' | 'verbose'
254
486
 
255
- // 手动日志输出
487
+ // Manual log output
256
488
  logger.log('Info message')
257
489
  logger.warn('Warning message')
258
490
  logger.error('Error message')
259
491
  ```
260
492
 
261
- ### 性能监控
493
+ ### Performance Monitoring
262
494
 
263
- SDK 提供了性能监控接口,可以监控渲染性能:
495
+ The SDK provides performance monitoring interfaces to monitor rendering performance:
264
496
 
265
497
  ```typescript
266
- // 获取渲染性能统计
498
+ // Get rendering performance statistics
267
499
  const stats = avatarView.getPerformanceStats()
268
500
 
269
501
  if (stats) {
270
- console.log(`渲染耗时: ${stats.renderTime.toFixed(2)}ms`)
271
- console.log(`排序耗时: ${stats.sortTime.toFixed(2)}ms`)
272
- console.log(`渲染后端: ${stats.backend}`)
502
+ console.log(`Render time: ${stats.renderTime.toFixed(2)}ms`)
503
+ console.log(`Sort time: ${stats.sortTime.toFixed(2)}ms`)
504
+ console.log(`Rendering backend: ${stats.backend}`)
273
505
 
274
- // 计算帧率
506
+ // Calculate frame rate
275
507
  const fps = 1000 / stats.renderTime
276
- console.log(`帧率: ${fps.toFixed(2)} FPS`)
508
+ console.log(`Frame rate: ${fps.toFixed(2)} FPS`)
277
509
  }
278
510
 
279
- // 定期监控性能
511
+ // Regular performance monitoring
280
512
  setInterval(() => {
281
513
  const stats = avatarView.getPerformanceStats()
282
514
  if (stats) {
283
- // 发送到监控服务或显示在 UI
515
+ // Send to monitoring service or display on UI
284
516
  console.log('Performance:', stats)
285
517
  }
286
518
  }, 1000)
287
519
  ```
288
520
 
289
- **性能统计说明**:
290
- - `renderTime`: 总渲染耗时(毫秒),包含排序和 GPU 渲染
291
- - `sortTime`: 排序耗时(毫秒),使用 Radix Sort 算法对点云进行深度排序
292
- - `backend`: 当前使用的渲染后端(`'webgpu'` | `'webgl'` | `null`)
521
+ **Performance Statistics Description:**
522
+ - `renderTime`: Total rendering time (milliseconds), includes sorting and GPU rendering
523
+ - `sortTime`: Sorting time (milliseconds), uses Radix Sort algorithm to depth-sort point cloud
524
+ - `backend`: Currently used rendering backend (`'webgpu'` | `'webgl'` | `null`)
293
525
 
294
- ## 🚨 错误处理
526
+ ## 🚨 Error Handling
295
527
 
296
528
  ### SPAvatarError
297
529
 
298
- SDK 使用自定义错误类型,提供更详细的错误信息:
530
+ The SDK uses custom error types, providing more detailed error information:
299
531
 
300
532
  ```typescript
301
533
  import { SPAvatarError } from '@spatialwalk/avatarkit'
@@ -311,65 +543,135 @@ try {
311
543
  }
312
544
  ```
313
545
 
314
- ### 错误回调
546
+ ### Error Callbacks
315
547
 
316
548
  ```typescript
317
549
  avatarView.avatarController.onError = (error: Error) => {
318
550
  console.error('AvatarController error:', error)
319
- // 处理错误,比如重连、用户提示等
551
+ // Handle error, such as reconnection, user notification, etc.
320
552
  }
321
553
  ```
322
554
 
323
- ## 🔄 资源管理
555
+ ## 🔄 Resource Management
324
556
 
325
- ### 生命周期管理
557
+ ### Lifecycle Management
558
+
559
+ #### Network Mode Lifecycle
326
560
 
327
561
  ```typescript
328
- // 初始化
329
- const avatarView = new AvatarView(avatar, container)
562
+ // Initialize
563
+ const container = document.getElementById('avatar-container')
564
+ const avatarView = new AvatarView(avatar, {
565
+ container: container,
566
+ playbackMode: AvatarPlaybackMode.network
567
+ })
330
568
  await avatarView.avatarController.start()
331
569
 
332
- // 使用
570
+ // Use
333
571
  avatarView.avatarController.send(audioData, false)
334
572
 
335
- // 清理
336
- avatarView.dispose() // 自动清理所有资源
573
+ // Cleanup
574
+ avatarView.avatarController.close()
575
+ avatarView.dispose() // Automatically cleans up all resources
576
+ ```
577
+
578
+ #### External Data Mode Lifecycle
579
+
580
+ ```typescript
581
+ // Initialize
582
+ const container = document.getElementById('avatar-container')
583
+ const avatarView = new AvatarView(avatar, {
584
+ container: container,
585
+ playbackMode: AvatarPlaybackMode.external
586
+ })
587
+
588
+ // Use
589
+ const initialAudioChunks = [{ data: audioData1, isLast: false }]
590
+ await avatarView.avatarController.play(initialAudioChunks, initialKeyframes)
591
+ avatarView.avatarController.sendAudioChunk(audioChunk, false)
592
+ avatarView.avatarController.sendKeyframes(keyframes)
593
+
594
+ // Cleanup
595
+ avatarView.avatarController.clear() // Clear all data and resources
596
+ avatarView.dispose() // Automatically cleans up all resources
337
597
  ```
338
598
 
339
- ### 内存优化
599
+ **⚠️ Important Notes:**
600
+ - SDK currently only supports one AvatarView instance at a time
601
+ - When switching characters, must first call `dispose()` to clean up old AvatarView, then create new instance
602
+ - Not properly cleaning up may cause resource leaks and rendering errors
603
+ - In network mode, call `close()` before `dispose()` to properly close WebSocket connections
604
+ - In external data mode, call `clear()` before `dispose()` to clear all playback data
605
+
606
+ ### Memory Optimization
607
+
608
+ - SDK automatically manages WASM memory allocation
609
+ - Supports dynamic loading/unloading of character and animation resources
610
+ - Provides memory usage monitoring interface
611
+
612
+ ### Audio Data Sending
613
+
614
+ #### Network Mode
340
615
 
341
- - SDK 自动管理 WASM 内存分配
342
- - 支持角色和动画资源的动态加载/卸载
343
- - 提供内存使用监控接口
616
+ The `send()` method receives audio data in `ArrayBuffer` format:
344
617
 
345
- ### 音频数据发送
618
+ **Audio Format Requirements:**
619
+ - **Sample Rate**: 16kHz (16000 Hz) - **Backend requirement, must be exactly 16kHz**
620
+ - **Format**: PCM16 (16-bit signed integer, little-endian)
621
+ - **Channels**: Mono (single channel)
622
+ - **Data Size**: Each sample is 2 bytes, so 1 second of audio = 16000 samples × 2 bytes = 32000 bytes
346
623
 
347
- `send()` 方法接收 `ArrayBuffer` 格式的音频数据:
624
+ **Usage:**
625
+ - `audioData`: Audio data (ArrayBuffer format, must be 16kHz mono PCM16)
626
+ - `end=false` (default) - Normal audio data sending, server will accumulate audio data, automatically returns animation data and starts synchronized playback of animation and audio after accumulating enough data
627
+ - `end=true` - Immediately return animation data, no longer accumulating, used for ending current conversation or scenarios requiring immediate response
628
+ - **Important**: No need to wait for `end=true` to start playing, it will automatically start playing after accumulating enough audio data
629
+
630
+ #### External Data Mode
631
+
632
+ The `play()` method starts playback with initial data, then use `sendAudioChunk()` to stream additional audio:
633
+
634
+ **Audio Format Requirements:**
635
+ - Same as network mode: 16kHz mono PCM16 format
636
+ - Audio data should be provided as `Uint8Array` in chunks with `isLast` flag
637
+
638
+ **Usage:**
639
+ ```typescript
640
+ // Start playback with initial audio and animation data
641
+ // Note: Audio and animation data should be obtained from your backend service
642
+ const initialAudioChunks = [
643
+ { data: audioData1, isLast: false },
644
+ { data: audioData2, isLast: false }
645
+ ]
646
+ await avatarController.play(initialAudioChunks, initialKeyframes)
647
+
648
+ // Stream additional audio chunks
649
+ avatarController.sendAudioChunk(audioChunk, isLast)
650
+ ```
348
651
 
349
- **使用说明:**
350
- - `audioData`: 音频数据(ArrayBuffer 格式)
351
- - `end=false`(默认)- 正常发送音频数据,服务端会积累音频数据,积累到一定量后会自动返回动画数据并开始同步播放动画和音频
352
- - `end=true` - 立即返回动画数据,不再积累,用于结束当前对话或需要立即响应的场景
353
- - **重要**:不需要等待 `end=true` 才开始播放,积累到一定音频数据后就会自动开始播放
652
+ **Resampling (Both Modes):**
653
+ - If your audio source is at a different sample rate (e.g., 24kHz, 48kHz), you **must** resample it to 16kHz before sending
654
+ - For high-quality resampling, use Web Audio API's `OfflineAudioContext` with anti-aliasing filtering
655
+ - See example projects (`vanilla`, `react`, `vue`) for complete resampling implementation
354
656
 
355
- ## 🌐 浏览器兼容性
657
+ ## 🌐 Browser Compatibility
356
658
 
357
- - **Chrome/Edge** 90+ (推荐 WebGPU)
659
+ - **Chrome/Edge** 90+ (WebGPU recommended)
358
660
  - **Firefox** 90+ (WebGL)
359
661
  - **Safari** 14+ (WebGL)
360
- - **移动端** iOS 14+, Android 8+
662
+ - **Mobile** iOS 14+, Android 8+
361
663
 
362
- ## 📝 许可证
664
+ ## 📝 License
363
665
 
364
666
  MIT License
365
667
 
366
- ## 🤝 贡献
668
+ ## 🤝 Contributing
367
669
 
368
- 欢迎提交 Issue Pull Request!
670
+ Issues and Pull Requests are welcome!
369
671
 
370
- ## 📞 支持
672
+ ## 📞 Support
371
673
 
372
- 如有问题,请联系:
373
- - 邮箱:support@spavatar.com
374
- - 文档:https://docs.spavatar.com
375
- - GitHubhttps://github.com/spavatar/sdk
674
+ For questions, please contact:
675
+ - Email: support@spavatar.com
676
+ - Documentation: https://docs.spavatar.com
677
+ - GitHub: https://github.com/spavatar/sdk