qt-human 2.1.0-alpha.9 → 2.2.0-alpha.2
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 +550 -1
- package/dist/bundle.esm.js +1 -1
- package/dist/bundle.iife.js +1 -1
- package/dist/bundle.umd.js +1 -1
- package/dist/index.d.ts +98 -115
- package/dist/types/api/human.d.ts +1 -0
- package/dist/types/const.d.ts +1 -1
- package/dist/types/modules/core/recorder.d.ts +1 -0
- package/dist/types/modules/core/recorder2.d.ts +1 -0
- package/dist/types/modules/core/render.d.ts +6 -6
- package/dist/types/modules/core/voice-interaction.d.ts +1 -0
- package/dist/types/modules/core/websocket.d.ts +2 -0
- package/dist/types/modules/human.d.ts +17 -30
- package/dist/types/types/index.d.ts +72 -79
- package/dist/types/utils/AudioManager.d.ts +45 -0
- package/dist/types/utils/framePlayer.d.ts +23 -0
- package/package.json +17 -16
package/README.md
CHANGED
|
@@ -1 +1,550 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Human 数字人接口使用文档
|
|
2
|
+
|
|
3
|
+
## 简介
|
|
4
|
+
|
|
5
|
+
Human 是一个用于控制和管理数字人的核心类,提供了丰富的功能来操作数字人的行为、语音和交互。该类继承自 Emittery,支持事件监听机制。
|
|
6
|
+
|
|
7
|
+
## 安装依赖
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
$ yarn add qt-human
|
|
11
|
+
# 或
|
|
12
|
+
$ npm i qt-human
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 初始化配置
|
|
16
|
+
|
|
17
|
+
### 基础配置
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
const config: QuanTe.Configuration = {
|
|
21
|
+
// 必填:授权token
|
|
22
|
+
token: string;
|
|
23
|
+
|
|
24
|
+
// 可选:模型容器,可以是DOM ID或HTMLElement
|
|
25
|
+
// 如果为空时表示只加载模型并不渲染
|
|
26
|
+
container?: string | HTMLElement;
|
|
27
|
+
|
|
28
|
+
// 可选:数字人ID
|
|
29
|
+
characterId?: string;
|
|
30
|
+
|
|
31
|
+
// 可选:音频配置
|
|
32
|
+
audio?: {
|
|
33
|
+
volumn?: number; // 音量大小,默认1.0
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// 可选:服务配置
|
|
37
|
+
server?: {
|
|
38
|
+
api?: string; // API接口地址
|
|
39
|
+
wss?: string; // WebSocket服务地址
|
|
40
|
+
questionApiParams?: { // 问答接口参数
|
|
41
|
+
model?: 'quan' | 'charglm-3' | 'qwen1.5' | 'glm-4' | 'openai' | 'echo';
|
|
42
|
+
stream?: boolean;
|
|
43
|
+
sentence?: boolean;
|
|
44
|
+
max_tokens?: number;
|
|
45
|
+
temperature?: number;
|
|
46
|
+
};
|
|
47
|
+
text2SpeachApiParams?: { // 语音合成参数
|
|
48
|
+
role?: 'woman' | 'man' | 'xiaoxiao' | 'yunxiao' | 'yunhao';
|
|
49
|
+
speed?: number;
|
|
50
|
+
model?: 'gpt-sovits' | 'xunfei' | 'paddle' | 'paddle2' | 'azure';
|
|
51
|
+
viseme?: 'azure' | 'ovr' | 'a2f' | 'qt' | 'none' | 'a2f3d';
|
|
52
|
+
smooth_method?: number;
|
|
53
|
+
smooth_interations?: number;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// 可选:模型配置
|
|
58
|
+
modelConfig?: {
|
|
59
|
+
name?: string;
|
|
60
|
+
camera?: {
|
|
61
|
+
fov?: number;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// 可选:加载提示元素
|
|
66
|
+
loading?: string | HTMLElement;
|
|
67
|
+
|
|
68
|
+
// 可选:是否在加载完成后销毁loading
|
|
69
|
+
loadingDestory?: boolean;
|
|
70
|
+
|
|
71
|
+
// 可选:其他配置选项
|
|
72
|
+
options?: {
|
|
73
|
+
fps?: number; // 帧率,默认30
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// 可选:模式,nomal 普通模式(默认), voice 语音控制, only_render 只渲染模型
|
|
77
|
+
mode?: 'voice' | 'nomal' | 'only_render';
|
|
78
|
+
// 语音交互模式配置
|
|
79
|
+
voiceModeConfig?: {
|
|
80
|
+
// 录音能量值,范围:0~100
|
|
81
|
+
level?: number
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 主要方法
|
|
87
|
+
|
|
88
|
+
### setCharacter
|
|
89
|
+
|
|
90
|
+
显示/切换数字人
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
setCharacter(characterId: string, configuration?: Partial<QuanTe.Configuration>): Promise<boolean>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
- `characterId`: 数字人ID
|
|
97
|
+
- `configuration`: 可选的配置参数
|
|
98
|
+
- 返回值: Promise<boolean> - 设置是否成功
|
|
99
|
+
|
|
100
|
+
### speak
|
|
101
|
+
|
|
102
|
+
让数字人说一段话
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
speak(text: string, callback?: Function, opt?: {[key: string]: any}): Promise<boolean>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
- `text`: 要说的文本内容
|
|
109
|
+
- `callback`: 可选的回调函数
|
|
110
|
+
- `opt`: 可选配置,如 `{ split: false }` 控制是否分段
|
|
111
|
+
- 返回值: Promise<boolean> - 说话是否成功
|
|
112
|
+
|
|
113
|
+
### ask
|
|
114
|
+
|
|
115
|
+
进行 AI 问答
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
ask(params: QuanTe.API.AskParams, callback: (msgs: IResultData<QuanTe.API.ChatMessage[]>) => void): Promise<QuanTe.Result<QuanTe.API.AskResponse>>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
- `params`: 问答参数
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
{
|
|
125
|
+
message: Array<{
|
|
126
|
+
// user: 用户提问,assistant:系统回答
|
|
127
|
+
role: 'user' | 'assistant';
|
|
128
|
+
// 内容
|
|
129
|
+
content: string;
|
|
130
|
+
}>;
|
|
131
|
+
// 会话ID
|
|
132
|
+
conversation_id?: string;
|
|
133
|
+
// 接口响应模式,streaming: 流式,blocking:非流式
|
|
134
|
+
response_mode?: 'streaming' | 'blocking';
|
|
135
|
+
// 上传文件
|
|
136
|
+
files?: Array<{
|
|
137
|
+
type: 'image';
|
|
138
|
+
// remote_url:远程网络地址, local_file:本地图片
|
|
139
|
+
transfer_method: 'remote_url' | 'local_file';
|
|
140
|
+
// 图片地址
|
|
141
|
+
url: string;
|
|
142
|
+
}>;
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
- `callback`: 回调函数,接收问答结果
|
|
147
|
+
|
|
148
|
+
### muteAudio
|
|
149
|
+
|
|
150
|
+
控制音频静音
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
muteAudio(isMute: boolean = true)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
- `isMute`: true 表示静音,false 表示取消静音
|
|
157
|
+
|
|
158
|
+
### muteAction
|
|
159
|
+
|
|
160
|
+
控制动作禁用
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
muteAction(isMute: boolean = true)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
- `isMute`: true 表示禁用动作,false 表示取消禁用
|
|
167
|
+
|
|
168
|
+
### startVoice2Text
|
|
169
|
+
|
|
170
|
+
开始录音转文本
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
startVoice2Text(callback: (data: QuanTe.Recorder.Voice2Text) => void): Promise<QuanTe.Result<QuanTe.Recorder.PermissionResult>>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
- `callback`: 回调函数,接收语音转文本结果
|
|
177
|
+
- 返回值: Promise<QuanTe.Result<QuanTe.Recorder.PermissionResult>>
|
|
178
|
+
|
|
179
|
+
### stopVoice2Text
|
|
180
|
+
|
|
181
|
+
结束录音转文本
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
stopVoice2Text(): Promise<QuanTe.Result<null>>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
- 返回值: Promise<QuanTe.Result<null>>
|
|
188
|
+
|
|
189
|
+
### stop
|
|
190
|
+
|
|
191
|
+
停止语音和口型动作
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
stop(): Promise<boolean>
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
- 返回值: Promise<boolean> - 停止是否成功
|
|
198
|
+
|
|
199
|
+
### speakByAudioShapes
|
|
200
|
+
|
|
201
|
+
根据音频地址和口型数据说话
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
speakByAudioShapes(uris: string[], shapes: Array<number[][]>): Promise<boolean>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
- `uris`: 音频资源地址数组
|
|
208
|
+
- `shapes`: 口型数据数组
|
|
209
|
+
- 返回值: Promise<boolean> - 说话是否成功
|
|
210
|
+
|
|
211
|
+
### updateToken
|
|
212
|
+
|
|
213
|
+
更新授权token
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
updateToken(token: string): void
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
- `token`: 新的授权token
|
|
220
|
+
|
|
221
|
+
### setAngleView
|
|
222
|
+
|
|
223
|
+
切换视角
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
setAngleView({ camera, controls }: {
|
|
227
|
+
camera: QuanTe.Model.TCamera & { duration?: number },
|
|
228
|
+
controls: QuanTe.Model.OrbitControl & { duration?: number }
|
|
229
|
+
}): void
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
- `camera`: 相机配置
|
|
233
|
+
- `controls`: 轨道控制器配置
|
|
234
|
+
|
|
235
|
+
### playAction
|
|
236
|
+
|
|
237
|
+
执行动画
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
playAction(code: string, opts: QuanTe.PlayActionOptions = {}): Promise<void>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
- `code`: 动画代码
|
|
244
|
+
- `opts`: 动画选项
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
{
|
|
248
|
+
loop?: THREE.AnimationActionLoopStyles;
|
|
249
|
+
repetitions?: number;
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### getModelInfo
|
|
254
|
+
|
|
255
|
+
获取模型信息
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
getModelInfo(): ModelInfo | null
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
- 返回值: ModelInfo | null - 模型信息对象或null
|
|
262
|
+
|
|
263
|
+
## 事件监听
|
|
264
|
+
|
|
265
|
+
Human 类支持以下事件,可以通过 `EmitEvent` 枚举来使用:
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
import { EmitEvent } from 'qt-human'
|
|
269
|
+
|
|
270
|
+
// 数字人加载进度
|
|
271
|
+
human.on(EmitEvent.HUMAN_LOAD_PROGRESS, (data: {
|
|
272
|
+
code: string, // 加载阶段:'download' | 'loaded'
|
|
273
|
+
progress: number, // 当前进度
|
|
274
|
+
total: number // 总进度
|
|
275
|
+
}) => {})
|
|
276
|
+
|
|
277
|
+
// 数字人准备就绪
|
|
278
|
+
human.on(EmitEvent.HUMAN_READY, () => {})
|
|
279
|
+
|
|
280
|
+
// 数字人错误
|
|
281
|
+
human.on(EmitEvent.HUMAN_ERROR, (data: {
|
|
282
|
+
code: string, // 错误代码
|
|
283
|
+
uri: string // 相关资源地址
|
|
284
|
+
}) => {})
|
|
285
|
+
|
|
286
|
+
// 音频播放
|
|
287
|
+
human.on(EmitEvent.AUDIO_PLAY, () => {})
|
|
288
|
+
|
|
289
|
+
// 音频暂停
|
|
290
|
+
human.on(EmitEvent.AUDIO_PAUSE, () => {})
|
|
291
|
+
|
|
292
|
+
// 动作待执行
|
|
293
|
+
human.on(EmitEvent.HUMAN_ACTION_PENDING, (actions: string[]) => {})
|
|
294
|
+
|
|
295
|
+
// 语音唤醒
|
|
296
|
+
human.on(EmitEvent.VOICE_WAKE, (data: any) => {})
|
|
297
|
+
|
|
298
|
+
// 语音休眠
|
|
299
|
+
human.on(EmitEvent.VOICE_SLEEP, (data: any) => {})
|
|
300
|
+
|
|
301
|
+
// 语音打断
|
|
302
|
+
human.on(EmitEvent.VOICE_INTERRUPT, (data: any) => {})
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### EmitEvent 事件说明
|
|
306
|
+
|
|
307
|
+
| 事件名称 | 说明 | 触发时机 | 事件数据 |
|
|
308
|
+
|---------|------|---------|---------|
|
|
309
|
+
| HUMAN_LOAD_PROGRESS | 数字人加载进度 | 模型加载过程中 | `{ code: 'download' \| 'loaded', progress: number, total: number }` |
|
|
310
|
+
| HUMAN_READY | 数字人准备就绪 | 模型加载完成,可以开始交互 | `void` |
|
|
311
|
+
| HUMAN_ERROR | 数字人错误 | 发生错误时 | `{ code: string, uri: string }` |
|
|
312
|
+
| AUDIO_PLAY | 音频播放 | 开始播放音频时 | `void` |
|
|
313
|
+
| AUDIO_PAUSE | 音频暂停 | 音频暂停时 | `void` |
|
|
314
|
+
| HUMAN_ACTION_PENDING | 动作待执行 | 有待执行的动作时 | `string[]` |
|
|
315
|
+
| VOICE_WAKE | 语音唤醒 | 语音交互被唤醒时 | `any` |
|
|
316
|
+
| VOICE_SLEEP | 语音休眠 | 语音交互进入休眠状态时 | `any` |
|
|
317
|
+
| VOICE_INTERRUPT | 语音打断 | 语音交互被用户打断时 | `any` |
|
|
318
|
+
| WAKE_RECORDER_START | 唤醒录音开始 | 语音交互被唤醒并开始录音时 | `any` |
|
|
319
|
+
| WAKE_RECORDER_STOP | 唤醒状态下结束录音 | 语音交互被唤醒并结束音时 | `any` |
|
|
320
|
+
| VOICE2TEXT | 语音转文本 | 语音识别结果返回时 | `{ is_final: boolean, text: string, wav_name: string }` |
|
|
321
|
+
| CORE_BUNDLES_LOADED | 模型加载完成 | 模型加载完成 | QuanTe.Loader.LoaderResponse[] 所有模型数据 |
|
|
322
|
+
| RECORDER_MESSAGE | 录音消息 | 开始录音 | pcm 录音数据 |
|
|
323
|
+
| RECORDER_START | 开始录音 | 当录音能量值达到15时 | |
|
|
324
|
+
| RECORDER_STOP | 结束录音 | 0.8秒内未收到能量值超过15时 | |
|
|
325
|
+
| RECORDER_SENDING | 录音中 | 每次发送websocket时 | |
|
|
326
|
+
| ASRTEXT | 语音转文本消息 | 收到 ASR 服务数据 | 文本数据 |
|
|
327
|
+
|
|
328
|
+
### 事件使用示例
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
import Human, { EmitEvent } from 'qt-human'
|
|
332
|
+
|
|
333
|
+
const human = new Human({
|
|
334
|
+
token: 'your-token',
|
|
335
|
+
container: 'container-id'
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// 监听加载进度
|
|
339
|
+
human.on(EmitEvent.HUMAN_LOAD_PROGRESS, (data) => {
|
|
340
|
+
console.log(`加载进度: ${data.progress}/${data.total}`);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
// 监听准备就绪
|
|
344
|
+
human.on(EmitEvent.HUMAN_READY, () => {
|
|
345
|
+
console.log('数字人已准备就绪,可以开始交互');
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// 监听错误
|
|
349
|
+
human.on(EmitEvent.HUMAN_ERROR, (error) => {
|
|
350
|
+
console.error('发生错误:', error);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
// 监听音频状态
|
|
354
|
+
human.on(EmitEvent.AUDIO_PLAY, () => {
|
|
355
|
+
console.log('开始播放音频');
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
human.on(EmitEvent.AUDIO_PAUSE, () => {
|
|
359
|
+
console.log('音频已暂停');
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
// 监听语音交互状态
|
|
363
|
+
human.on(EmitEvent.VOICE_WAKE, () => {
|
|
364
|
+
console.log('语音交互已唤醒');
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
human.on(EmitEvent.VOICE_SLEEP, () => {
|
|
368
|
+
console.log('语音交互已休眠');
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
human.on(EmitEvent.VOICE_INTERRUPT, () => {
|
|
372
|
+
console.log('语音交互被用户打断');
|
|
373
|
+
});
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## 使用示例
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
import Human, { EmitEvent } from 'qt-human'
|
|
380
|
+
import type { QuanTe } from 'qt-human'
|
|
381
|
+
|
|
382
|
+
// 创建数字人实例
|
|
383
|
+
const human = new Human({
|
|
384
|
+
token: 'your-token',
|
|
385
|
+
container: 'container-id'
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
// 监听事件
|
|
389
|
+
human.on(EmitEvent.HUMAN_READY, () => {
|
|
390
|
+
console.log('数字人准备就绪');
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
// characterId: 数字人ID, 请登录 qtworld 平台复制数字人ID
|
|
394
|
+
human.setCharacter('characterId');
|
|
395
|
+
|
|
396
|
+
// 让数字人说话
|
|
397
|
+
human.speak('你好,我是数字人');
|
|
398
|
+
|
|
399
|
+
// AI问答
|
|
400
|
+
human.ask({
|
|
401
|
+
// 请求id,非必填
|
|
402
|
+
reqId: 'abcdefg',
|
|
403
|
+
message: [{ role: 'user', content: '你好' }]
|
|
404
|
+
}, (msgs: IResultData<QuanTe.API.ChatMessage[]>) => {
|
|
405
|
+
// 大模型流式推送结果
|
|
406
|
+
console.log(msgs);
|
|
407
|
+
}).then((result: QuanTe.Result<QuanTe.API.AskResponse>) => {
|
|
408
|
+
// 所有语音播放结束后返回bs等数据
|
|
409
|
+
console.log('result....', result)
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
// 控制音频
|
|
413
|
+
human.muteAudio(true); // 静音
|
|
414
|
+
human.muteAudio(false); // 取消静音
|
|
415
|
+
|
|
416
|
+
// 开始录音
|
|
417
|
+
human.startVoice2Text((data: QuanTe.Recorder.Voice2Text) => {
|
|
418
|
+
// 语音转文本内容
|
|
419
|
+
console.log(data)
|
|
420
|
+
})
|
|
421
|
+
// 结束录音语音转文本
|
|
422
|
+
human.stopVoice2Text()
|
|
423
|
+
|
|
424
|
+
// 通过 audio 和 bs 数据驱动数字人说话
|
|
425
|
+
human.speakByAudioShapes(['https://xxx/audio.wav', 'https://xxx/audio2.wav'], [[[...52个数据],[...52个数据]], [[...52个数据]]])
|
|
426
|
+
|
|
427
|
+
// 停止(停止语音、动作、口型动画、接口请求和待执行的任务队列等)并执行待机动画
|
|
428
|
+
human.stop()
|
|
429
|
+
|
|
430
|
+
// 销毁实例
|
|
431
|
+
human.destroy();
|
|
432
|
+
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
## 语音交互模式的使用
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
import Human, { EmitEvent } from 'qt-human'
|
|
439
|
+
|
|
440
|
+
// 1、创建数字人对象并设置语音模式
|
|
441
|
+
const human = new Human({
|
|
442
|
+
token: 'your-token',
|
|
443
|
+
container: 'container-id',
|
|
444
|
+
mode: 'voice'
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
// 数字人准备就绪
|
|
448
|
+
human.on(EmitEvent.HUMAN_READY, () => {
|
|
449
|
+
// 2、开启语音交互
|
|
450
|
+
human.openVoiceInteraction({
|
|
451
|
+
// 唤醒词
|
|
452
|
+
wakeWords: ['小全小全', '你好小全'],
|
|
453
|
+
// 退出词(休眠)
|
|
454
|
+
exitWords: ['退出', '关闭'],
|
|
455
|
+
// 打断词
|
|
456
|
+
interruptWorlds: ['停止', '返回']
|
|
457
|
+
})
|
|
458
|
+
});
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
## 注意事项
|
|
462
|
+
|
|
463
|
+
1. 使用前必须配置有效的 token
|
|
464
|
+
2. 部分方法需要等待模型加载完成(HUMAN_READY 事件触发后)才能调用
|
|
465
|
+
3. 注意及时销毁实例以释放资源
|
|
466
|
+
4. 音频和动作控制可以根据需要随时切换
|
|
467
|
+
5. 建议在组件销毁时调用 destroy() 方法清理资源
|
|
468
|
+
|
|
469
|
+
## 获取 characterId 和 token
|
|
470
|
+
|
|
471
|
+
- characterId
|
|
472
|
+
创建 Human 对象时所需的 characterId 请登录 qtworld 平台获取,[qtworld 地址: https://ai.quantekeji.com/platform/login](https://ai.quantekeji.com/platform/login)
|
|
473
|
+
- token
|
|
474
|
+
获取 token 请调用数字人授权接口
|
|
475
|
+
|
|
476
|
+
## 数字人授权接口
|
|
477
|
+
|
|
478
|
+
### 接口说明
|
|
479
|
+
获取数字人访问令牌(token),用于初始化 Human 对象。
|
|
480
|
+
|
|
481
|
+
### 请求信息
|
|
482
|
+
- 请求方式:POST
|
|
483
|
+
- 接口地址:`https://ai.quantekeji.com/platform-api/human-auth/get-token`
|
|
484
|
+
|
|
485
|
+
### 请求参数
|
|
486
|
+
```typescript
|
|
487
|
+
{
|
|
488
|
+
// 应用秘钥(不要将秘钥保存在前端)
|
|
489
|
+
secretKey: string;
|
|
490
|
+
|
|
491
|
+
// 访问者ID(需要唯一)
|
|
492
|
+
visitorId: string;
|
|
493
|
+
|
|
494
|
+
// 访问者名称
|
|
495
|
+
visitorName: string;
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### 响应参数
|
|
500
|
+
```typescript
|
|
501
|
+
{
|
|
502
|
+
// 状态码:0 表示成功
|
|
503
|
+
code: number;
|
|
504
|
+
|
|
505
|
+
// 返回数据:JWT-TOKEN
|
|
506
|
+
data: string;
|
|
507
|
+
|
|
508
|
+
// 响应消息
|
|
509
|
+
msg: string;
|
|
510
|
+
}
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### 使用示例
|
|
514
|
+
|
|
515
|
+
```typescript
|
|
516
|
+
// 使用 axios 发起请求
|
|
517
|
+
import axios from 'axios';
|
|
518
|
+
|
|
519
|
+
async function getToken() {
|
|
520
|
+
try {
|
|
521
|
+
const response = await axios.post('https://ai.quantekeji.com/platform-api/human-auth/get-token', {
|
|
522
|
+
secretKey: 'your-secret-key',
|
|
523
|
+
visitorId: 'unique-visitor-id',
|
|
524
|
+
visitorName: 'visitor-name'
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
if (response.data.code === 0) {
|
|
528
|
+
const token = response.data.data;
|
|
529
|
+
// 使用获取到的 token 初始化 Human 对象
|
|
530
|
+
const human = new Human({
|
|
531
|
+
token,
|
|
532
|
+
container: 'container-id'
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
} catch (error) {
|
|
536
|
+
console.error('获取 token 失败:', error);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
### 注意事项
|
|
542
|
+
1. secretKey 是敏感信息,不要在前端代码中直接存储,在 [qtworld](https://ai.quantekeji.com/platform/login) 平台个人中心获取
|
|
543
|
+
2. visitorId 需要保证唯一性,建议使用用户ID或其他唯一标识
|
|
544
|
+
3. token 有效期通常为 2 小时,过期后需要重新获取
|
|
545
|
+
4. 建议在服务端调用此接口,避免暴露 secretKey
|
|
546
|
+
5. 获取到 token 后,请妥善保存,用于初始化 Human 对象
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
|