@zeewain/3d-avatar-sdk 1.0.8 → 1.1.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.
Files changed (33) hide show
  1. package/README.md +498 -149
  2. package/dist/assets/Build/webgl.data.unityweb +0 -0
  3. package/dist/assets/Build/webgl.framework.js.unityweb +0 -0
  4. package/dist/assets/Build/webgl.wasm.unityweb +0 -0
  5. package/dist/core/errors/error-codes.d.ts +122 -0
  6. package/dist/core/errors/index.d.ts +6 -0
  7. package/dist/core/errors/sdk-error.d.ts +84 -0
  8. package/dist/core/index.d.ts +15 -10
  9. package/dist/core/loaders/unity.d.ts +5 -7
  10. package/dist/core/managers/config.d.ts +68 -0
  11. package/dist/core/services/avatar.d.ts +130 -0
  12. package/dist/core/services/base-service.d.ts +123 -0
  13. package/dist/core/services/broadcast.d.ts +176 -0
  14. package/dist/core/services/index.d.ts +6 -0
  15. package/dist/core/{config → utils}/env.d.ts +1 -15
  16. package/dist/index.d.ts +819 -249
  17. package/dist/index.es5.d.ts +2 -1
  18. package/dist/index.es5.js +1798 -577
  19. package/dist/index.es5.umd.js +1798 -577
  20. package/dist/index.esm.js +1461 -511
  21. package/dist/index.umd.cjs +1464 -511
  22. package/dist/types/avatar.d.ts +87 -0
  23. package/dist/types/base-service.d.ts +111 -0
  24. package/dist/{core/interfaces → types}/broadcast.d.ts +56 -9
  25. package/dist/types/config.d.ts +31 -0
  26. package/dist/{core/interfaces → types}/index.d.ts +1 -0
  27. package/dist/{core/interfaces → types}/instance.d.ts +2 -2
  28. package/package.json +3 -2
  29. package/dist/core/api/avatar.d.ts +0 -138
  30. package/dist/core/api/broadcast.d.ts +0 -148
  31. package/dist/core/api/index.d.ts +0 -6
  32. package/dist/core/interfaces/avatar.d.ts +0 -41
  33. package/dist/core/interfaces/config.d.ts +0 -23
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  ## 1. 产品说明
4
4
  ### 1.1 产品概述
5
5
  紫为云3D写真数字人SDK采用多项AI技术实现:
6
- - 人脸重建与表情拟人化
6
+ - 仿真数字人渲染
7
7
  - 音频唇形精准驱动
8
8
  - 多终端语音交互
9
9
  - 支持PC/Web/APP/H5全平台
@@ -15,8 +15,7 @@
15
15
  |:--------------:|--------------------------------------------------------------------------|
16
16
  | **语音模块** | • 语音/文本对话管理 • 多终端接入控制 • 专属音色 |
17
17
  | **交互模块** | • 语音对话交互 • TTS语音播报 • 大屏字幕同步显示 |
18
- | **系统功能** | • 多背景切换 • 对话能力配置 • 实时测试体验 |
19
-
18
+ | **系统功能** | • 多背景切换 • 对话能力配置 • 实时测试体验 • 统一错误管理 |
20
19
 
21
20
  ## 2. SDK使用说明
22
21
  ### 2.1 核心功能
@@ -26,7 +25,7 @@
26
25
  | **数字人播报** | 通过文本/音频驱动口型表情 | ✅ |
27
26
  | **播报控制** | 启动/暂停/继续/停止播报 | ✅ |
28
27
  | **动作控制** | 播放预设动作库(招手/点头等) | ✅ |
29
-
28
+ | **错误管理** | 统一的错误处理系统,分类错误码,中文化错误消息 | ✅ |
30
29
 
31
30
  ### 2.2 安装方式
32
31
  #### 2.2.1 npm安装
@@ -40,18 +39,35 @@ npm install @zeewain/3d-avatar-sdk
40
39
  ##### ES6+ 模块方式(推荐)
41
40
  适用于现代浏览器和构建工具(Webpack、Vite、Rollup等)
42
41
  ```javascript
43
- // 自动选择最佳版本(ES6+ 环境使用 ES 模块,Node.js 环境使用 CommonJS)
44
- import { ZEEAvatarLoader, AvatarAPI, BroadcastService } from '@zeewain/3d-avatar-sdk'
42
+ // 导入核心模块
43
+ import { ZEEAvatarLoader, AvatarService, BroadcastService } from '@zeewain/3d-avatar-sdk'
44
+
45
+ // 导入类型定义(TypeScript 项目)
46
+ import {
47
+ IAvatarAPI,
48
+ IAvatarCallbackResponse,
49
+ AvatarCameraType,
50
+ BroadcastType,
51
+ IBroadcastParams,
52
+ IBroadcastCallbacks,
53
+ // 错误管理相关类型
54
+ SDKError,
55
+ NetworkErrorCode,
56
+ OperationErrorCode,
57
+ ResourceErrorCode,
58
+ SystemErrorCode,
59
+ ConfigErrorCode
60
+ } from '@zeewain/3d-avatar-sdk'
45
61
  ```
46
62
 
47
63
  ##### ES5 兼容方式
48
64
  适用于需要支持 IE11 等老旧浏览器的项目
49
65
  ```javascript
50
66
  // ES5 模块导入(包含完整 polyfill)
51
- import { ZEEAvatarLoader, AvatarAPI, BroadcastService } from '@zeewain/3d-avatar-sdk/es5'
67
+ import { ZEEAvatarLoader, AvatarService, BroadcastService } from '@zeewain/3d-avatar-sdk/es5'
52
68
 
53
69
  // ES5 CommonJS 导入
54
- const { ZEEAvatarLoader, AvatarAPI, BroadcastService } = require('@zeewain/3d-avatar-sdk/es5')
70
+ const { ZEEAvatarLoader, AvatarService, BroadcastService } = require('@zeewain/3d-avatar-sdk/es5')
55
71
  ```
56
72
 
57
73
  #### 2.2.3 通过 CDN 引入
@@ -60,7 +76,7 @@ const { ZEEAvatarLoader, AvatarAPI, BroadcastService } = require('@zeewain/3d-av
60
76
  ```html
61
77
  <!-- ES 模块方式 -->
62
78
  <script type="module">
63
- import { ZEEAvatarLoader, AvatarAPI, BroadcastService } from 'https://unpkg.com/@zeewain/3d-avatar-sdk'
79
+ import { ZEEAvatarLoader, AvatarService, BroadcastService } from 'https://unpkg.com/@zeewain/3d-avatar-sdk'
64
80
  // 使用 SDK...
65
81
  </script>
66
82
  ```
@@ -70,7 +86,7 @@ const { ZEEAvatarLoader, AvatarAPI, BroadcastService } = require('@zeewain/3d-av
70
86
  <!-- UMD 方式,支持现代浏览器 -->
71
87
  <script src="https://unpkg.com/@zeewain/3d-avatar-sdk"></script>
72
88
  <script>
73
- const { ZEEAvatarLoader, AvatarAPI, BroadcastService } = window.ZEEAvatarSDK;
89
+ const { ZEEAvatarLoader, AvatarService, BroadcastService } = window.ZEEAvatarSDK;
74
90
  // 使用 SDK...
75
91
  </script>
76
92
  ```
@@ -80,7 +96,7 @@ const { ZEEAvatarLoader, AvatarAPI, BroadcastService } = require('@zeewain/3d-av
80
96
  <!-- ES5 兼容版本,包含完整 polyfill -->
81
97
  <script src="https://unpkg.com/@zeewain/3d-avatar-sdk/es5"></script>
82
98
  <script>
83
- const { ZEEAvatarLoader, AvatarAPI, BroadcastService } = window.ZEEAvatarSDK;
99
+ const { ZEEAvatarLoader, AvatarService, BroadcastService } = window.ZEEAvatarSDK;
84
100
  // 使用 SDK...
85
101
  </script>
86
102
  ```
@@ -102,22 +118,34 @@ SDK 使用现代化的 `exports` 字段,支持自动版本选择:
102
118
  - **老旧工具**:回退到传统的 `main`/`module` 字段
103
119
 
104
120
  ### 2.3 接口说明
105
- #### 2.3.1 创建Unity实例
106
- 首先需要配置Unity WebGL构建文件的路径,将通过npm安装的 `@zeewain/3d-avatar-sdk/dist/assets/Build/` 目录下的内容放置在开发工程目录下:
121
+ #### 2.3.1 SDK初始化
122
+ 首先需要配置Unity WebGL构建文件的路径和认证信息:
107
123
 
108
124
  ```javascript
125
+ // SDK配置
109
126
  const config = {
110
- loaderUrl: './node_modules/@zeewain/3d-avatar-sdk/dist/assets/Build/webgl.loader.js',
111
- dataUrl: './node_modules/@zeewain/3d-avatar-sdk/dist/assets/Build/webgl.data.unityweb',
112
- frameworkUrl: './node_modules/@zeewain/3d-avatar-sdk/dist/assets/Build/webgl.framework.js.unityweb',
113
- codeUrl: './node_modules/@zeewain/3d-avatar-sdk/dist/assets/Build/webgl.wasm.unityweb',
127
+ // Unity构建文件路径配置
128
+ loaderUrl: './assets/Build/webgl.loader.js',
129
+ dataUrl: './assets/Build/webgl.data.unityweb',
130
+ frameworkUrl: './assets/Build/webgl.framework.js.unityweb',
131
+ codeUrl: './assets/Build/webgl.wasm.unityweb',
132
+
133
+ // 容器配置
114
134
  containerId: 'unity-container', // 页面中放置Unity容器的元素ID
135
+
136
+ // 认证配置
137
+ token: 'your-auth-token', // 用户认证token
138
+ env: 'prod', // 环境:'prod' | 'test' | 'custom',默认'prod'
139
+ apiUrl: 'https://your-custom-api.com', // 仅当 env='custom' 时需要
140
+
141
+ // 可选回调
115
142
  onProgress: (progress) => {
116
143
  console.log(`加载进度: ${Math.round(progress * 100)}%`);
117
144
  }
118
145
  };
119
146
 
120
- const sdk = new ZEEAvatarLoader(config);
147
+ // 创建SDK实例
148
+ const loader = new ZEEAvatarLoader(config);
121
149
  ```
122
150
 
123
151
  > **💡 提示**:Unity 资源文件较大(约19MB),建议:
@@ -125,121 +153,169 @@ const sdk = new ZEEAvatarLoader(config);
125
153
  > - 在生产环境中配置适当的缓存策略
126
154
  > - 考虑使用 IndexedDB 缓存以加速二次加载
127
155
 
128
- #### 2.3.2 初始化SDK
129
- 调用init()方法加载并初始化Unity环境
156
+ #### 2.3.2 初始化Unity环境
157
+ 调用init()方法加载并初始化Unity环境,获取Avatar API实例:
158
+
130
159
  ```javascript
131
- // 非私有化部署示例:
160
+ let avatarAPI;
161
+ let broadcastService;
162
+
132
163
  try {
133
- await sdk.init();
164
+ // 初始化SDK,返回Avatar API实例
165
+ avatarAPI = await loader.init();
134
166
  console.log('SDK 初始化成功!');
135
167
 
136
- // 获取Unity实例
137
- const instance = sdk.getInstance();
138
- const containerId = sdk.getContainerId();
139
-
140
- // 创建API实例
141
- const apiInstance = new AvatarAPI(instance, containerId);
168
+ // 获取Unity实例(可选)
169
+ const unityInstance = loader.getInstance();
170
+ const containerId = loader.getContainerId();
142
171
 
143
172
  // 创建播报服务实例
144
- const broadcastService = new BroadcastService(
145
- 'prod', // 非私有化部署,只能用这个,否则会访问不到
146
- () => localStorage.getItem('zee_token'), // 获取token的函数
147
- instance
148
- );
173
+ broadcastService = new BroadcastService({
174
+ unityInstance: unityInstance,
175
+ callbacks: {
176
+ onStart: () => console.log('播报开始'),
177
+ onFinish: () => console.log('播报完成'),
178
+ onError: (error) => console.error('播报错误:', error),
179
+ onPause: () => console.log('播报暂停'),
180
+ onResume: () => console.log('播报恢复'),
181
+ onStop: () => console.log('播报停止')
182
+ }
183
+ });
184
+
149
185
  } catch (error) {
150
186
  console.error('SDK 初始化失败:', error);
151
187
  }
152
-
153
- // 私有化部署配置示例
154
- const broadcastService = new BroadcastService(
155
- "https://your-private-domain.com", // 私有化域名
156
- () => localStorage.getItem('zee_token'),
157
- instance
158
- );
159
188
  ```
160
189
 
161
190
  #### 2.3.3 销毁SDK实例
162
191
  在不需要Unity的时候释放Unity实例:
163
192
  ```javascript
164
- sdk.destroy();
193
+ // 销毁播报服务
194
+ if (broadcastService) {
195
+ broadcastService.destroy();
196
+ }
197
+
198
+ // 销毁SDK实例
199
+ loader.destroy();
165
200
  console.log('Unity环境已销毁');
166
201
  ```
167
202
 
168
-
169
203
  #### 2.3.4 加载数字人
170
204
  ```javascript
171
- const response = await apiInstance.initializeAvatar(token, avatarCode);
172
- if (response.success) {
173
- console.log('数字人加载成功');
205
+ try {
206
+ const response = await avatarAPI.initializeAvatar(avatarCode, 'whole');
207
+ if (response.success) {
208
+ console.log('数字人加载成功');
209
+ } else {
210
+ console.error('数字人加载失败:', response.message);
211
+ }
212
+ } catch (error) {
213
+ console.error('加载异常:', error);
174
214
  }
175
215
  ```
176
216
 
177
217
  | 参数 | 类型 | 必填项 | 说明 |
178
218
  | :---: | :---: | :---:| :---: |
179
- | token | string |是 | 用户认证token,详见token获取说明文档 |
180
- | avatarCode | string |是 | 数字人编码 |
219
+ | avatarCode | string |✅ | 数字人编码 |
220
+ | cameraType | AvatarCameraType |❌ | 摄像机类型:'whole' \| 'half' \| 'face',默认'whole' |
181
221
 
182
- - 返回值:0 表示成功, 失败返回错误码信息以及失败原因。
222
+ **返回值**:`Promise<IAvatarCallbackResponse>` - 包含操作结果的Promise对象
183
223
 
184
- #### 2.4.5 播放动作
224
+ #### 2.3.5 播放动作
185
225
  ```javascript
186
- const response = await apiInstance.playMotion(token, clipCode);
187
- if (response.success) {
188
- console.log('动作播放成功');
226
+ try {
227
+ const response = await avatarAPI.playMotion(clipCode);
228
+ if (response.success) {
229
+ console.log('动作播放成功');
230
+ }
231
+ } catch (error) {
232
+ console.error('动作播放失败:', error);
189
233
  }
190
234
  ```
191
235
 
192
236
  | 参数 | 类型 | 必填项 | 说明 |
193
237
  | :---: | :---: | :---:| :---: |
194
- | token | string |✅ | 用户认证token |
195
238
  | clipCode | string |✅ | 动作编码 |
196
- - 返回值:0 表示成功, 失败返回错误码信息以及失败原因。
197
239
 
198
- #### 2.4.6 获取当前动作信息
240
+ **返回值**:`Promise<IAvatarCallbackResponse>` -Promise对象
241
+
242
+ #### 2.3.6 获取当前动作信息
199
243
  ```javascript
200
- // 获取动作编码和剩余时间
201
- const response = await apiInstance.getCurrentMotion(true);
202
- console.log('动作编码:', response.motionId);
203
- console.log('剩余时间:', response.motionRemainingTime); // 当动作为待机状态(如呼吸动画)时,motionRemainingTime 固定返回0
204
-
205
- // 获取动作编码
206
- const response = await apiInstance.getCurrentMotion(false);
207
- console.log('动作编码:', response.motionId);
244
+ try {
245
+ // 获取动作编码和剩余时间
246
+ const response = await avatarAPI.getCurrentMotion(true);
247
+ if (response.success) {
248
+ console.log('动作编码:', response.data.motionId);
249
+ console.log('剩余时间:', response.data.motionRemainingTime); // 待机状态时返回0
250
+ }
251
+
252
+ // 仅获取动作编码
253
+ const response2 = await avatarAPI.getCurrentMotion(false);
254
+ console.log('动作编码:', response2.motionId);
255
+ } catch (error) {
256
+ console.error('获取动作信息失败:', error);
257
+ }
208
258
  ```
209
259
 
210
260
  | 参数 | 类型 | 必填项 | 说明 |
211
261
  | :---: | :---: | :---:| :---: |
212
- | token | string |✅ | 用户认证token |
213
262
  | getRemainingTime | boolean |✅ | 是否获取动作剩余时间|
214
- - 返回值:0 表示成功, 失败返回错误码信息以及失败原因。
215
263
 
216
- #### 2.4.7 播报服务
264
+ **返回值**:`Promise<IAvatarCallbackResponse>` - 包含动作信息的Promise对象
265
+
266
+ #### 2.3.7 设置摄像机类型
267
+ ```javascript
268
+ try {
269
+ const response = await avatarAPI.setCamera('face');
270
+ if (response.success) {
271
+ console.log('摄像机设置成功');
272
+ }
273
+ } catch (error) {
274
+ console.error('摄像机设置失败:', error);
275
+ }
276
+ ```
277
+
278
+ | 参数 | 类型 | 必填项 | 说明 |
279
+ | :---: | :---: | :---:| :---: |
280
+ | type | AvatarCameraType |✅ | 摄像机类型:'whole' \| 'half' \| 'face'|
281
+
282
+ #### 2.3.8 播报服务
217
283
  ```javascript
218
284
  // 文本播报
219
- await broadcastService.startBroadcast(token, {
220
- type: "text",
221
- humanCode: avatarCode,
222
- text: "欢迎使用紫为云3D数字人交互SDK",
223
- voiceCode: "VOICE001",
224
- volume: 1.0,
225
- speed: 1.0,
226
- isSubtitle: false
227
- });
285
+ try {
286
+ await broadcastService.startBroadcast({
287
+ type: BroadcastType.TEXT, // 或 'text'
288
+ humanCode: avatarCode,
289
+ text: "欢迎使用紫为云3D数字人交互SDK",
290
+ voiceCode: "VOICE001",
291
+ volume: 1.0,
292
+ speed: 1.0,
293
+ isSubtitle: false
294
+ });
295
+ } catch (error) {
296
+ console.error('文本播报失败:', error);
297
+ }
228
298
 
229
299
  // 音频播报
230
- await broadcastService.startBroadcast(token, {
231
- type: "audio",
232
- humanCode: avatarCode,
233
- audioUrl: "https://example.com/audio.mp3",
234
- text: "音频字幕内容",
235
- volume: 1.0,
236
- isSubtitle: true
237
- });
300
+ try {
301
+ await broadcastService.startBroadcast({
302
+ type: BroadcastType.AUDIO, // 或 'audio'
303
+ humanCode: avatarCode,
304
+ audioUrl: "https://example.com/audio.mp3",
305
+ text: "音频字幕内容",
306
+ volume: 1.0,
307
+ isSubtitle: true
308
+ });
309
+ } catch (error) {
310
+ console.error('音频播报失败:', error);
311
+ }
238
312
  ```
239
313
 
314
+ **播报参数说明**:
315
+
240
316
  | 参数 | 类型 | 必填项 | 说明 |
241
317
  | :---: | :---: | :---:| :---: |
242
- | type | string |✅ | 播报类型:'text'或'audio' |
318
+ | type | BroadcastType |✅ | 播报类型:'text'或'audio' |
243
319
  | humanCode | string |✅ | 数字人编码 |
244
320
  | text | string |✅ | 播报文本内容 |
245
321
  | voiceCode | string |文本播报✅<br/>音频播报❌| 音色编码 |
@@ -247,89 +323,323 @@ await broadcastService.startBroadcast(token, {
247
323
  | volume | number |❌ | 音量 (0-1.0) 默认:1.0|
248
324
  | speed | number |❌ | 语速 (0.5-2.0)默认:1.0|
249
325
  | isSubtitle | boolean |❌ | 是否启用字幕 (暂不支持)|
250
- - 返回值:0 表示成功, 失败返回错误码信息以及失败原因。
251
326
 
252
- #### 2.4.8 暂停播报
327
+ #### 2.3.9 播报控制
253
328
  ```javascript
254
- await broadcastService.pauseBroadcast(token);
329
+ // 暂停播报
330
+ try {
331
+ await broadcastService.pauseBroadcast();
332
+ console.log('播报已暂停');
333
+ } catch (error) {
334
+ console.error('暂停失败:', error);
335
+ }
336
+
337
+ // 恢复播报
338
+ try {
339
+ await broadcastService.resumeBroadcast();
340
+ console.log('播报已恢复');
341
+ } catch (error) {
342
+ console.error('恢复失败:', error);
343
+ }
344
+
345
+ // 停止播报
346
+ try {
347
+ await broadcastService.stopBroadcast();
348
+ console.log('播报已停止');
349
+ } catch (error) {
350
+ console.error('停止失败:', error);
351
+ }
255
352
  ```
256
- | 参数 | 类型 | 必填项 | 说明 |
257
- | :---: | :---: | :---:| :---: |
258
- | token | string |✅ | 用户认证token |
259
353
 
260
- #### 2.4.9 恢复播报
354
+ #### 2.3.10 卸载数字人
261
355
  ```javascript
262
- await broadcastService.resumeBroadcast(token);
356
+ try {
357
+ const response = await avatarAPI.unloadAvatar();
358
+ if (response.success) {
359
+ console.log('数字人卸载成功');
360
+ }
361
+ } catch (error) {
362
+ console.error('数字人卸载失败:', error);
363
+ }
263
364
  ```
264
- | 参数 | 类型 | 必填项 | 说明 |
265
- | :---: | :---: | :---:| :---: |
266
- | token | string |✅ | 用户认证token |
267
365
 
268
- #### 2.4.10 结束播报
366
+ **返回值**:`Promise<IAvatarCallbackResponse>` - 包含操作结果的Promise对象
367
+
368
+ #### 2.3.11 批量操作
269
369
  ```javascript
270
- await broadcastService.stopBroadcast(token);
370
+ // 批量执行多个操作
371
+ try {
372
+ const results = await avatarAPI.batchExecute([
373
+ { method: 'initializeAvatar', params: ['avatar001', 'whole'] },
374
+ { method: 'playMotion', params: ['motion001'] },
375
+ { method: 'setCamera', params: ['face'] }
376
+ ]);
377
+
378
+ results.forEach((result, index) => {
379
+ if (result.success) {
380
+ console.log(`操作 ${index + 1} 成功`);
381
+ } else {
382
+ console.error(`操作 ${index + 1} 失败:`, result.message);
383
+ }
384
+ });
385
+ } catch (error) {
386
+ console.error('批量操作异常:', error);
387
+ }
271
388
  ```
272
- | 参数 | 类型 | 必填项 | 说明 |
273
- | :---: | :---: | :---:| :---: |
274
- | token | string |✅ | 用户认证token |
275
389
 
276
- #### 2.4.11 卸载数字人
390
+ #### 2.3.12 播报状态管理
277
391
  ```javascript
278
- const response = await apiInstance.unloadAvatar(token);
279
- if (response.success) {
280
- console.log('数字人卸载成功');
281
- }
392
+ // 获取播报状态
393
+ const status = broadcastService.getStatus();
394
+ console.log('播报状态:', {
395
+ isActive: status.isActive,
396
+ pendingCallbacks: status.pendingCallbacks,
397
+ hasController: status.hasController
398
+ });
399
+
400
+ // 更新播报回调
401
+ broadcastService.updateCallbacks({
402
+ onStart: () => console.log('新的开始回调'),
403
+ onError: (error) => console.error('新的错误回调:', error)
404
+ });
282
405
  ```
283
- | 参数 | 类型 | 必填项 | 说明 |
284
- | :---: | :---: | :---:| :---: |
285
- | token | string |✅ | 用户认证token |
286
- - 返回值:0 表示成功, 失败返回错误码信息以及失败原因。
287
406
 
288
- ### 2.5 错误处理
289
- SDK中的操作可能会抛出异常,建议使用try-catch处理:
407
+ ### 2.4 错误处理
408
+ SDK中的操作都返回Promise,建议使用try-catch处理异常。SDK使用统一的错误管理系统,所有错误都继承自`SDKError`类:
409
+
290
410
  ```javascript
291
- // try-catch 示例:
411
+ // 导入错误类型和错误码(TypeScript项目)
412
+ import { SDKError, NetworkErrorCode, OperationErrorCode, ResourceErrorCode, SystemErrorCode, ConfigErrorCode } from '@zeewain/3d-avatar-sdk'
413
+
414
+ // 统一错误处理示例
292
415
  try {
293
- await apiInstance.initializeAvatar(token, avatarCode);
416
+ const response = await avatarAPI.initializeAvatar('avatar001');
417
+ if (response.success) {
418
+ console.log('数字人加载成功');
419
+ }
294
420
  } catch (error) {
295
- console.error('数字人加载失败:', error.message);
421
+ // 处理SDK错误
422
+ if (error instanceof SDKError) {
423
+ handleSDKError(error);
424
+ } else {
425
+ // 处理其他系统异常
426
+ console.error('系统异常:', error.message);
427
+ }
428
+ }
429
+
430
+ // SDK错误处理
431
+ function handleSDKError(error) {
432
+ console.error('SDK错误:', error.message, '错误码:', error.code);
296
433
 
297
- // 根据错误类型进行特定处理
298
- if (error.message.includes('Token无效')) {
299
- // 重新获取token
434
+ // 根据错误类别处理
435
+ switch (error.category) {
436
+ case 'NETWORK':
437
+ handleNetworkError(error);
438
+ break;
439
+ case 'OPERATION':
440
+ handleOperationError(error);
441
+ break;
442
+ case 'RESOURCE':
443
+ handleResourceError(error);
444
+ break;
445
+ case 'SYSTEM':
446
+ handleSystemError(error);
447
+ break;
448
+ case 'CONFIG':
449
+ handleConfigError(error);
450
+ break;
451
+ default:
452
+ console.error('未知错误类别:', error.category);
453
+ }
454
+ }
455
+
456
+ // 网络错误处理
457
+ function handleNetworkError(error) {
458
+ switch (error.code) {
459
+ case NetworkErrorCode.CONNECTION_FAILED:
460
+ console.error('网络连接失败,请检查网络状态');
461
+ break;
462
+ case NetworkErrorCode.REQUEST_TIMEOUT:
463
+ console.error('请求超时,请稍后重试');
464
+ break;
465
+ case NetworkErrorCode.SERVER_ERROR:
466
+ console.error('服务器错误,请稍后重试');
467
+ break;
468
+ case NetworkErrorCode.UNAUTHORIZED:
469
+ console.error('认证失效,请重新登录');
470
+ // 跳转到登录页面或刷新token
471
+ break;
300
472
  }
301
473
  }
302
474
 
303
- // 错误码处理示例:
304
- catch (error) {
305
- switch (error.code) {
306
- case 7: // Token失效
307
- await refreshToken();
308
- break;
309
- case 2: // 网络错误
310
- showToast("网络异常,请检查连接");
311
- break;
312
- default:
313
- console.error(`未知错误: ${error.code}`);
314
- }
475
+ // 操作错误处理
476
+ function handleOperationError(error) {
477
+ switch (error.code) {
478
+ case OperationErrorCode.UNITY_NOT_INITIALIZED:
479
+ console.error('Unity实例未初始化');
480
+ break;
481
+ case OperationErrorCode.AVATAR_NOT_LOADED:
482
+ console.error('数字人未加载,请先加载数字人');
483
+ break;
484
+ case OperationErrorCode.OPERATION_FAILED:
485
+ console.error('操作执行失败');
486
+ break;
487
+ case OperationErrorCode.OPERATION_TIMEOUT:
488
+ console.error('操作超时,请稍后重试');
489
+ break;
490
+ case OperationErrorCode.OPERATION_CANCELLED:
491
+ console.error('操作已取消');
492
+ break;
493
+ }
494
+ }
495
+
496
+ // 资源错误处理
497
+ function handleResourceError(error) {
498
+ switch (error.code) {
499
+ case ResourceErrorCode.LOAD_FAILED:
500
+ console.error('资源加载失败');
501
+ break;
502
+ case ResourceErrorCode.FILE_CORRUPTED:
503
+ console.error('资源文件损坏');
504
+ break;
505
+ case ResourceErrorCode.NOT_FOUND:
506
+ console.error('资源不存在');
507
+ break;
508
+ case ResourceErrorCode.UNSUPPORTED_FORMAT:
509
+ console.error('资源格式不支持');
510
+ break;
511
+ }
512
+ }
513
+
514
+ // 系统错误处理
515
+ function handleSystemError(error) {
516
+ if (error instanceof SDKError) {
517
+ switch (error.code) {
518
+ case SystemErrorCode.OUT_OF_MEMORY:
519
+ console.error('内存不足,请关闭其他应用');
520
+ break;
521
+ case SystemErrorCode.GPU_NOT_SUPPORTED:
522
+ console.error('GPU不支持,请更新浏览器或显卡驱动');
523
+ break;
524
+ case SystemErrorCode.WEBGL_NOT_SUPPORTED:
525
+ console.error('浏览器不支持WebGL');
526
+ break;
527
+ case SystemErrorCode.BROWSER_NOT_COMPATIBLE:
528
+ console.error('浏览器不兼容,请更新浏览器');
529
+ break;
530
+ }
531
+ } else {
532
+ console.error('系统异常:', error.message);
533
+ // 可以上报错误日志
534
+ }
315
535
  }
536
+
537
+ // 配置错误处理
538
+ function handleConfigError(error) {
539
+ switch (error.code) {
540
+ case ConfigErrorCode.INVALID_CONFIG:
541
+ console.error('配置参数无效');
542
+ break;
543
+ case ConfigErrorCode.MISSING_REQUIRED_PARAM:
544
+ console.error('缺少必需参数');
545
+ break;
546
+ case ConfigErrorCode.PARAM_OUT_OF_RANGE:
547
+ console.error('参数值超出范围');
548
+ break;
549
+ case ConfigErrorCode.INVALID_JSON_FORMAT:
550
+ console.error('JSON格式错误');
551
+ break;
552
+ }
553
+ }
554
+
555
+ // 播报错误处理
556
+ const broadcastService = new BroadcastService({
557
+ unityInstance: unityInstance,
558
+ callbacks: {
559
+ onError: (error) => {
560
+ // 所有错误都是SDKError类型
561
+ console.error('播报错误:', error.message, '错误码:', error.code);
562
+ handleSDKError(error);
563
+ }
564
+ }
565
+ });
316
566
  ```
317
567
 
318
- ### 2.6 返回编码以及对应信息参考表
568
+ ### 2.5 SDK错误码参考表
319
569
 
320
- | 返回编码 | 编码名称 | 描述说明 | 常见发生场景 |
570
+ SDK使用统一的错误管理系统,所有错误都通过`SDKError`抛出:
571
+
572
+ ##### 网络错误 (1xxx)
573
+ | 错误码 | 常量名 | 描述说明 | 常见发生场景 |
321
574
  | :---: | :---: | :---: | :---: |
322
- | 0 | 成功 | 操作成功 | 返回、操作结果正常|
323
- | 1 | 资源加载失败 | Unity资源加载失败 | Unity AssetBundle加载失败、纹理、音频等资源加载失败等|
324
- | 2 | 网络通信错误 | 网络请求相关错误 | 下载超时、连接中断、服务器错误等 |
325
- | 3 | 配置参数错误 | 配置数据错误或缺失 |Json解析失败、参数缺失、路径错误等 |
326
- | 4 | 操作执行错误 | 特定操作执行失败 | 动画播放失败、装扮应用失败、在非常规下操作数字人导致的问题等 |
327
- | 5 | 系统资源不足 | 系统资源限制 | 内存不足、GPU资源不足等 |
328
- | 6 | 状态冲突错误 | 当前状态不允许执行此操作 | 在非准备状态下执行操作等 |
329
- | 7 | 数据验证错误 | 数据验证或者格式错误 | 许可证无效、数据校验失败、token过期等 |
330
- | 8 | 第三方依赖错误 | 外部依赖或服务错误 | 云服务不可用、第三方SDK引用失败等 |
331
- | 9 | 其他 | 未知 | 未知 |
575
+ | 1001 | `NetworkErrorCode.CONNECTION_FAILED` | 网络连接失败 | 网络不可用、防火墙阻止、DNS解析失败 |
576
+ | 1002 | `NetworkErrorCode.REQUEST_TIMEOUT` | 请求超时 | 网络延迟过高、服务器响应慢 |
577
+ | 1003 | `NetworkErrorCode.SERVER_ERROR` | 服务器错误 | 服务器内部错误、API异常 |
578
+ | 1004 | `NetworkErrorCode.UNAUTHORIZED` | 未授权访问 | Token失效、权限不足 |
579
+
580
+ ##### 操作错误 (2xxx)
581
+ | 错误码 | 常量名 | 描述说明 | 常见发生场景 |
582
+ | :---: | :---: | :---: | :---: |
583
+ | 2001 | `OperationErrorCode.UNITY_NOT_INITIALIZED` | Unity实例未初始化 | 在Unity加载完成前调用API |
584
+ | 2002 | `OperationErrorCode.AVATAR_NOT_LOADED` | 数字人未加载 | 在数字人加载完成前调用相关API |
585
+ | 2003 | `OperationErrorCode.OPERATION_FAILED` | 操作执行失败 | Unity操作执行失败、消息发送失败、播报处理失败等 |
586
+ | 2004 | `OperationErrorCode.OPERATION_TIMEOUT` | 操作超时 | 操作执行时间过长 |
587
+ | 2005 | `OperationErrorCode.OPERATION_CANCELLED` | 操作被取消 | 用户主动取消或系统中断 |
588
+
589
+ ##### 资源错误 (3xxx)
590
+ | 错误码 | 常量名 | 描述说明 | 常见发生场景 |
591
+ | :---: | :---: | :---: | :---: |
592
+ | 3001 | `ResourceErrorCode.LOAD_FAILED` | 资源加载失败 | 文件不存在、下载失败 |
593
+ | 3002 | `ResourceErrorCode.FILE_CORRUPTED` | 资源文件损坏 | 文件格式错误、数据损坏 |
594
+ | 3003 | `ResourceErrorCode.NOT_FOUND` | 资源不存在 | 指定的资源路径不存在 |
595
+ | 3004 | `ResourceErrorCode.UNSUPPORTED_FORMAT` | 资源格式不支持 | 音频格式不支持、模型格式不兼容 |
596
+
597
+ ##### 系统错误 (4xxx)
598
+ | 错误码 | 常量名 | 描述说明 | 常见发生场景 |
599
+ | :---: | :---: | :---: | :---: |
600
+ | 4001 | `SystemErrorCode.OUT_OF_MEMORY` | 内存不足 | 系统内存不足、浏览器内存限制 |
601
+ | 4002 | `SystemErrorCode.GPU_NOT_SUPPORTED` | GPU不支持 | 显卡不支持WebGL、驱动过旧 |
602
+ | 4003 | `SystemErrorCode.WEBGL_NOT_SUPPORTED` | WebGL不支持 | 浏览器不支持WebGL |
603
+ | 4004 | `SystemErrorCode.BROWSER_NOT_COMPATIBLE` | 浏览器不兼容 | 浏览器版本过低、功能不支持 |
604
+
605
+ ##### 配置错误 (5xxx)
606
+ | 错误码 | 常量名 | 描述说明 | 常见发生场景 |
607
+ | :---: | :---: | :---: | :---: |
608
+ | 5001 | `ConfigErrorCode.INVALID_CONFIG` | 配置参数无效 | 配置格式错误、参数类型不匹配 |
609
+ | 5002 | `ConfigErrorCode.MISSING_REQUIRED_PARAM` | 必需参数缺失 | 缺少必需的配置项或参数 |
610
+ | 5003 | `ConfigErrorCode.PARAM_OUT_OF_RANGE` | 参数值超出范围 | 参数值超出有效范围 |
611
+ | 5004 | `ConfigErrorCode.INVALID_JSON_FORMAT` | JSON格式错误 | JSON解析失败、格式不正确 |
612
+
613
+ #### 2.5.1 错误码使用示例
332
614
 
615
+ ```javascript
616
+ // 检查具体的错误码
617
+ try {
618
+ await avatarAPI.initializeAvatar('avatar001');
619
+ } catch (error) {
620
+ if (error instanceof SDKError) {
621
+ // 使用错误码常量进行判断
622
+ if (error.code === OperationErrorCode.UNITY_NOT_INITIALIZED) {
623
+ console.error('Unity实例未初始化');
624
+ } else if (error.code === OperationErrorCode.OPERATION_FAILED) {
625
+ console.error('操作执行失败');
626
+ } else if (error.code === NetworkErrorCode.UNAUTHORIZED) {
627
+ console.error('认证失效,请重新登录');
628
+ }
629
+
630
+ // 或者使用错误类别进行判断
631
+ switch (error.category) {
632
+ case 'NETWORK':
633
+ console.error('网络错误:', error.message);
634
+ break;
635
+ case 'OPERATION':
636
+ console.error('操作错误:', error.message);
637
+ break;
638
+ // ... 其他类别
639
+ }
640
+ }
641
+ }
642
+ ```
333
643
 
334
644
  ## 3. 注意事项
335
645
  ### 3.1 Unity构建文件
@@ -342,10 +652,12 @@ catch (error) {
342
652
  ### 3.3 数字人加载和卸载时机
343
653
  - 数字人加载成功后,才能卸载数字人。
344
654
  - 在未成功加载数字人的时候,提前卸载数字人,卸载会成功,但是会导致第二次加载数字人失败;解决方案:卸载Unity实例化,重新初始化Unity,再初始化数字人即可解决。
345
- - 目前版本不支持数字人的返回进度,后续版本会提供。
346
655
  ### 3.4 错误处理
347
- - 所有异步操作都可能抛出异常,务必使用try-catch处理。
348
- - 检查错误消息中包含的具体错误原因。
656
+ - 所有异步操作都返回Promise,务必使用try-catch处理。
657
+ - 检查response.success字段判断操作是否成功。
658
+ - **统一错误管理系统**:所有错误都通过`SDKError`抛出,通过错误码和错误类别进行精确处理。
659
+ - SDK错误码采用分类编码:网络错误(1xxx)、操作错误(2xxx)、资源错误(3xxx)、系统错误(4xxx)、配置错误(5xxx)。
660
+ - 所有错误消息已本地化为中文,可直接显示给用户。
349
661
  ### 3.5 性能考虑
350
662
  - 避免频繁加载/卸载数字人。
351
663
  - 音频文件不易过大。(建议<5MB)
@@ -367,17 +679,19 @@ catch (error) {
367
679
  - **移动设备**:注意性能限制,考虑降低渲染质量
368
680
  - **资源缓存**:Web端建议对Unity资源文件使用 IndexedDB 缓存
369
681
  - **网络优化**:将Unity资源部署到CDN以提高加载速度
370
- ### 3.7 关于必填参数
371
- - 所有标注为✅ 的参数必须提供。
372
- - token失效会导致接口调用失败。
682
+
683
+ ### 3.7 认证配置
684
+ - token在SDK初始化时配置,无需在每个API调用时传递
685
+ - token失效时,需要重新初始化SDK或更新全局配置
686
+ - 支持生产环境('prod')、测试环境('test')和自定义环境('custom')
373
687
 
374
688
  ## 4. 常见问题
375
689
  ### 4.1 Unity内容无法加载怎么办?
376
690
 
377
691
  1. 确保Unity构建文件路径配置正确;
378
692
  2. 检查浏览器控制台是否有CORS错误;
379
- 3. 确认网络可以访问构建文件URL;
380
- 4. 验证Unity版本与SDK兼容性;
693
+ 3. 确认网络可以访问构建文件URL;
694
+ 4. 验证Unity版本与SDK兼容性;
381
695
 
382
696
  ### 4.2 播报没有声音怎么办?
383
697
 
@@ -402,3 +716,38 @@ catch (error) {
402
716
 
403
717
  1. 请联系技术支持获取可用音色编码列表;
404
718
 
719
+ ### 4.6 如何处理SDK错误?
720
+
721
+ 1. **统一错误管理系统**:所有错误都通过`SDKError`抛出,使用try-catch捕获异常;
722
+ 2. **错误码分类**:根据错误码前缀快速定位问题类型(1xxx网络、2xxx操作、3xxx资源、4xxx系统、5xxx配置);
723
+ 3. **错误消息本地化**:所有错误消息已中文化,可直接显示给用户;
724
+ 4. **调试技巧**:使用`error.category`进行错误分类处理,使用`error.code`进行精确判断;
725
+ 5. **最佳实践**:建议根据错误类别统一处理,提供友好的用户提示;
726
+
727
+ ### 4.7 新版本API迁移说明
728
+
729
+ 如果您从旧版本SDK升级,主要变化:
730
+
731
+ 1. **类名变化**:`AvatarAPI` → `AvatarService`(但通过`IAvatarAPI`接口使用)
732
+ 2. **初始化方式**:token在SDK初始化时配置,不再在每个方法中传递
733
+ 3. **返回值**:所有方法都返回Promise,不再使用回调函数
734
+ 4. **参数简化**:方法参数更简洁,移除了重复的token参数
735
+ 5. **类型安全**:完整的TypeScript类型定义,更好的开发体验
736
+ 6. **错误管理升级**:
737
+ - 统一的`SDKError`错误类型,替代原有的`UnityServiceError`
738
+ - 采用分类错误码系统(1xxx-5xxx),便于精确处理
739
+ - 所有错误消息中文化,提供更友好的用户体验
740
+ - 支持错误类别判断,简化错误处理逻辑
741
+ - 所有错误都通过异常抛出,统一错误处理方式
742
+
743
+ ---
744
+
745
+ ## 📋 更新日志
746
+
747
+ ### 最新版本特性
748
+ - ✅ **统一错误管理系统**:全新的`SDKError`错误类型,替代原有的`UnityServiceError`
749
+ - ✅ **分类错误码**:采用5类错误码系统(1xxx-5xxx),便于精确处理和调试
750
+ - ✅ **中文化错误消息**:所有错误消息本地化为中文,提升用户体验
751
+ - ✅ **TypeScript完整支持**:完整的错误类型定义,更好的开发体验
752
+ - ✅ **统一异常处理**:所有错误都通过异常抛出,简化错误处理逻辑
753
+