@zeewain/3d-avatar-sdk 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1606 -753
- package/dist/assets/Build/webgl.data.unityweb +0 -0
- package/dist/assets/Build/webgl.framework.js.unityweb +0 -0
- package/dist/assets/Build/webgl.wasm.unityweb +0 -0
- package/dist/index.d.ts +363 -238
- package/dist/index.es5.js +60 -129
- package/dist/index.es5.umd.js +60 -129
- package/dist/index.esm.js +338 -73
- package/dist/index.umd.cjs +339 -73
- package/package.json +1 -1
- package/dist/core/errors/error-codes.d.ts +0 -122
- package/dist/core/errors/index.d.ts +0 -6
- package/dist/core/errors/sdk-error.d.ts +0 -84
- package/dist/core/index.d.ts +0 -80
- package/dist/core/loaders/index.d.ts +0 -5
- package/dist/core/loaders/unity.d.ts +0 -51
- package/dist/core/managers/config.d.ts +0 -68
- package/dist/core/services/avatar.d.ts +0 -130
- package/dist/core/services/base-service.d.ts +0 -123
- package/dist/core/services/broadcast.d.ts +0 -176
- package/dist/core/services/index.d.ts +0 -6
- package/dist/core/utils/env.d.ts +0 -30
- package/dist/index.es5.d.ts +0 -9
- package/dist/types/avatar.d.ts +0 -87
- package/dist/types/base-service.d.ts +0 -111
- package/dist/types/broadcast.d.ts +0 -178
- package/dist/types/config.d.ts +0 -31
- package/dist/types/index.d.ts +0 -9
- package/dist/types/instance.d.ts +0 -28
package/README.md
CHANGED
|
@@ -1,753 +1,1606 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
//
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
} catch (error) {
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
//
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
//
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
1
|
+
# ZEE 3D Avatar SDK 使用说明
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
[](https://badge.fury.io/js/@zeewain/3d-avatar-sdk)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## 🚀 产品概述
|
|
8
|
+
|
|
9
|
+
紫为云3D写真数字人SDK采用多项AI技术实现:
|
|
10
|
+
- **仿真数字人渲染** - 高保真3D数字人模型渲染
|
|
11
|
+
- **音频唇形精准驱动** - 智能口型同步技术
|
|
12
|
+
- **多终端语音交互** - 支持PC/Web/APP/H5全平台
|
|
13
|
+
- **统一SDK架构** - 单一入口,简化集成流程
|
|
14
|
+
|
|
15
|
+
**应用场景**:智能客服 | 智慧政务 | 文旅会展 | 数字营销 | 在线教育
|
|
16
|
+
|
|
17
|
+
## ✨ 核心特性
|
|
18
|
+
|
|
19
|
+
### 🎯 统一架构设计
|
|
20
|
+
- **单一入口**:`ZEEAvatarSDK` 类统一管理所有功能
|
|
21
|
+
- **组合模式**:内部整合Avatar控制、播报服务等模块
|
|
22
|
+
- **多实例支持**:同一页面可创建多个独立SDK实例
|
|
23
|
+
- **回调隔离**:每个实例拥有独立的回调函数命名空间
|
|
24
|
+
|
|
25
|
+
### 🛡️ 完善的错误管理
|
|
26
|
+
- **统一错误类型**:`SDKError` 统一错误处理
|
|
27
|
+
- **分类错误码**:网络(1xxx)、操作(2xxx)、资源(3xxx)、系统(4xxx)、配置(5xxx)
|
|
28
|
+
- **中文化消息**:所有错误消息本地化,用户友好
|
|
29
|
+
- **详细调试信息**:错误类别、错误码、详细描述
|
|
30
|
+
|
|
31
|
+
### 🔧 开发者友好
|
|
32
|
+
- **完整TypeScript支持**:全类型定义,智能提示
|
|
33
|
+
- **Promise-based API**:现代异步编程模式
|
|
34
|
+
- **统一配置管理**:一次配置,全局生效
|
|
35
|
+
- **生命周期管理**:完善的资源清理机制
|
|
36
|
+
|
|
37
|
+
## 📦 安装方式
|
|
38
|
+
|
|
39
|
+
> **WebGL文件来源说明**:
|
|
40
|
+
> - 所有WebGL构建文件(webgl.loader.js、webgl.data.unityweb、webgl.framework.js.unityweb、webgl.wasm.unityweb)均来源于SDK包(@zeewain/3d-avatar-sdk)的`dist/assets/Build/`目录。
|
|
41
|
+
> - 使用SDK前,请先将这些文件从 `node_modules/@zeewain/3d-avatar-sdk/dist/assets/Build/` 目录拷贝到你项目的静态资源目录,如 `public` 目录或你的CDN服务器上。
|
|
42
|
+
> - 然后在SDK初始化时,通过config参数设置这些WebGL文件的路径。
|
|
43
|
+
|
|
44
|
+
### npm/yarn 安装(推荐)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# npm
|
|
48
|
+
npm install @zeewain/3d-avatar-sdk
|
|
49
|
+
|
|
50
|
+
# yarn
|
|
51
|
+
yarn add @zeewain/3d-avatar-sdk
|
|
52
|
+
|
|
53
|
+
# pnpm
|
|
54
|
+
pnpm add @zeewain/3d-avatar-sdk
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### CDN 引入
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<!-- ES 模块方式(现代浏览器) -->
|
|
61
|
+
<script type="module">
|
|
62
|
+
import { ZEEAvatarSDK } from 'https://unpkg.com/@zeewain/3d-avatar-sdk'
|
|
63
|
+
// 使用 SDK...
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<!-- UMD 方式(全局变量) -->
|
|
67
|
+
<script src="https://unpkg.com/@zeewain/3d-avatar-sdk"></script>
|
|
68
|
+
<script>
|
|
69
|
+
const { ZEEAvatarSDK } = window.ZEEAvatarSDKLib;
|
|
70
|
+
// 使用 SDK...
|
|
71
|
+
</script>
|
|
72
|
+
|
|
73
|
+
<!-- ES5 兼容版本(支持IE11) -->
|
|
74
|
+
<script src="https://unpkg.com/@zeewain/3d-avatar-sdk/es5"></script>
|
|
75
|
+
<script>
|
|
76
|
+
const { ZEEAvatarSDK } = window.ZEEAvatarSDKLib;
|
|
77
|
+
// 使用 SDK...
|
|
78
|
+
</script>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
> **💡 重要说明**:
|
|
82
|
+
> - **SDK类名**:`ZEEAvatarSDK`(这是您在代码中使用的类)
|
|
83
|
+
> - **UMD全局变量名**:`ZEEAvatarSDKLib`(这是挂载到window对象的变量名)
|
|
84
|
+
> - 使用UMD方式时,需要从 `window.ZEEAvatarSDKLib` 中解构出 `ZEEAvatarSDK` 类
|
|
85
|
+
|
|
86
|
+
## 🎮 快速开始
|
|
87
|
+
|
|
88
|
+
### 基础使用示例
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
import { ZEEAvatarSDK, AvatarCameraType, BroadcastType } from '@zeewain/3d-avatar-sdk'
|
|
92
|
+
|
|
93
|
+
// 1. 创建SDK实例
|
|
94
|
+
const sdk = new ZEEAvatarSDK({
|
|
95
|
+
// Unity构建文件配置
|
|
96
|
+
loaderUrl: './assets/Build/webgl.loader.js',
|
|
97
|
+
dataUrl: './assets/Build/webgl.data.unityweb',
|
|
98
|
+
frameworkUrl: './assets/Build/webgl.framework.js.unityweb',
|
|
99
|
+
codeUrl: './assets/Build/webgl.wasm.unityweb',
|
|
100
|
+
|
|
101
|
+
// 基础配置
|
|
102
|
+
containerId: 'unity-container',
|
|
103
|
+
token: 'your-auth-token',
|
|
104
|
+
env: 'prod',
|
|
105
|
+
|
|
106
|
+
// 加载进度回调
|
|
107
|
+
onProgress: (progress) => {
|
|
108
|
+
console.log(`加载进度: ${Math.round(progress * 100)}%`);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// 2. 初始化数字人
|
|
113
|
+
async function initializeAvatar() {
|
|
114
|
+
try {
|
|
115
|
+
const response = await sdk.initializeAvatar('avatar001', AvatarCameraType.WHOLE);
|
|
116
|
+
if (response.success) {
|
|
117
|
+
console.log('数字人初始化成功!');
|
|
118
|
+
|
|
119
|
+
// 3. 播放动作
|
|
120
|
+
await sdk.playMotion('wave_hand');
|
|
121
|
+
|
|
122
|
+
// 4. 开始播报
|
|
123
|
+
await sdk.startBroadcast({
|
|
124
|
+
type: BroadcastType.TEXT,
|
|
125
|
+
humanCode: 'avatar001',
|
|
126
|
+
text: '欢迎使用ZEE 3D Avatar SDK!',
|
|
127
|
+
voiceCode: 'VOICE001',
|
|
128
|
+
volume: 1.0,
|
|
129
|
+
speed: 1.0,
|
|
130
|
+
isSubtitle: false
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error('初始化失败:', error);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// 5. 页面卸载时清理资源
|
|
139
|
+
window.addEventListener('beforeunload', () => {
|
|
140
|
+
sdk.destroy();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// 开始初始化
|
|
144
|
+
initializeAvatar();
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 完整应用示例
|
|
148
|
+
|
|
149
|
+
```javascript
|
|
150
|
+
import {
|
|
151
|
+
ZEEAvatarSDK,
|
|
152
|
+
AvatarCameraType,
|
|
153
|
+
BroadcastType,
|
|
154
|
+
SDKError,
|
|
155
|
+
NetworkErrorCode,
|
|
156
|
+
OperationErrorCode
|
|
157
|
+
} from '@zeewain/3d-avatar-sdk'
|
|
158
|
+
|
|
159
|
+
class AvatarApp {
|
|
160
|
+
constructor() {
|
|
161
|
+
this.sdk = null;
|
|
162
|
+
this.isInitialized = false;
|
|
163
|
+
this.setupUI();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 初始化SDK
|
|
167
|
+
async initSDK() {
|
|
168
|
+
try {
|
|
169
|
+
this.sdk = new ZEEAvatarSDK({
|
|
170
|
+
loaderUrl: './assets/Build/webgl.loader.js',
|
|
171
|
+
dataUrl: './assets/Build/webgl.data.unityweb',
|
|
172
|
+
frameworkUrl: './assets/Build/webgl.framework.js.unityweb',
|
|
173
|
+
codeUrl: './assets/Build/webgl.wasm.unityweb',
|
|
174
|
+
containerId: 'unity-container',
|
|
175
|
+
token: 'your-auth-token',
|
|
176
|
+
env: 'prod',
|
|
177
|
+
onProgress: this.onLoadProgress.bind(this)
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// 初始化数字人
|
|
181
|
+
const response = await this.sdk.initializeAvatar('avatar001', AvatarCameraType.WHOLE);
|
|
182
|
+
|
|
183
|
+
if (response.success) {
|
|
184
|
+
this.isInitialized = true;
|
|
185
|
+
this.updateUI();
|
|
186
|
+
console.log('SDK初始化成功');
|
|
187
|
+
}
|
|
188
|
+
} catch (error) {
|
|
189
|
+
this.handleError(error);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// 播放动作
|
|
194
|
+
async playMotion(motionCode) {
|
|
195
|
+
if (!this.isInitialized) {
|
|
196
|
+
console.warn('SDK未初始化');
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
const response = await this.sdk.playMotion(motionCode);
|
|
202
|
+
if (response.success) {
|
|
203
|
+
console.log('动作播放成功');
|
|
204
|
+
}
|
|
205
|
+
} catch (error) {
|
|
206
|
+
this.handleError(error);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// 文本播报
|
|
211
|
+
async speakText(text, voiceCode = 'VOICE001') {
|
|
212
|
+
if (!this.isInitialized) {
|
|
213
|
+
console.warn('SDK未初始化');
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
await this.sdk.startBroadcast({
|
|
219
|
+
type: BroadcastType.TEXT,
|
|
220
|
+
humanCode: 'avatar001',
|
|
221
|
+
text: text,
|
|
222
|
+
voiceCode: voiceCode,
|
|
223
|
+
volume: 1.0,
|
|
224
|
+
speed: 1.0,
|
|
225
|
+
isSubtitle: false
|
|
226
|
+
});
|
|
227
|
+
console.log('播报开始');
|
|
228
|
+
} catch (error) {
|
|
229
|
+
this.handleError(error);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// 音频播报
|
|
234
|
+
async playAudio(audioUrl, subtitleText = '') {
|
|
235
|
+
if (!this.isInitialized) {
|
|
236
|
+
console.warn('SDK未初始化');
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
try {
|
|
241
|
+
await this.sdk.startBroadcast({
|
|
242
|
+
type: BroadcastType.AUDIO,
|
|
243
|
+
humanCode: 'avatar001',
|
|
244
|
+
audioUrl: audioUrl,
|
|
245
|
+
text: subtitleText,
|
|
246
|
+
volume: 1.0,
|
|
247
|
+
isSubtitle: true
|
|
248
|
+
});
|
|
249
|
+
console.log('音频播报开始');
|
|
250
|
+
} catch (error) {
|
|
251
|
+
this.handleError(error);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// 播报控制
|
|
256
|
+
async pauseBroadcast() {
|
|
257
|
+
try {
|
|
258
|
+
await this.sdk.pauseBroadcast();
|
|
259
|
+
console.log('播报已暂停');
|
|
260
|
+
} catch (error) {
|
|
261
|
+
this.handleError(error);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async resumeBroadcast() {
|
|
266
|
+
try {
|
|
267
|
+
await this.sdk.resumeBroadcast();
|
|
268
|
+
console.log('播报已恢复');
|
|
269
|
+
} catch (error) {
|
|
270
|
+
this.handleError(error);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async stopBroadcast() {
|
|
275
|
+
try {
|
|
276
|
+
await this.sdk.stopBroadcast();
|
|
277
|
+
console.log('播报已停止');
|
|
278
|
+
} catch (error) {
|
|
279
|
+
this.handleError(error);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// 摄像机控制
|
|
284
|
+
async setCamera(cameraType) {
|
|
285
|
+
if (!this.isInitialized) {
|
|
286
|
+
console.warn('SDK未初始化');
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
try {
|
|
291
|
+
const response = await this.sdk.setCamera(cameraType);
|
|
292
|
+
if (response.success) {
|
|
293
|
+
console.log('摄像机设置成功');
|
|
294
|
+
}
|
|
295
|
+
} catch (error) {
|
|
296
|
+
this.handleError(error);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// 获取当前动作信息
|
|
301
|
+
async getCurrentMotion() {
|
|
302
|
+
if (!this.isInitialized) {
|
|
303
|
+
console.warn('SDK未初始化');
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
try {
|
|
308
|
+
const response = await this.sdk.getCurrentMotion(true);
|
|
309
|
+
if (response.success) {
|
|
310
|
+
console.log('当前动作:', response.data);
|
|
311
|
+
return response.data;
|
|
312
|
+
}
|
|
313
|
+
} catch (error) {
|
|
314
|
+
this.handleError(error);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// 加载进度回调
|
|
319
|
+
onLoadProgress(progress) {
|
|
320
|
+
const percent = Math.round(progress * 100);
|
|
321
|
+
console.log(`加载进度: ${percent}%`);
|
|
322
|
+
// 更新进度条UI
|
|
323
|
+
this.updateProgressBar(percent);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// 错误处理
|
|
327
|
+
handleError(error) {
|
|
328
|
+
console.error('SDK错误:', error);
|
|
329
|
+
|
|
330
|
+
if (error instanceof SDKError) {
|
|
331
|
+
switch (error.code) {
|
|
332
|
+
case NetworkErrorCode.CONNECTION_FAILED:
|
|
333
|
+
this.showMessage('网络连接失败,请检查网络状态', 'error');
|
|
334
|
+
break;
|
|
335
|
+
case NetworkErrorCode.UNAUTHORIZED:
|
|
336
|
+
this.showMessage('认证失效,请重新登录', 'error');
|
|
337
|
+
break;
|
|
338
|
+
case OperationErrorCode.UNITY_NOT_INITIALIZED:
|
|
339
|
+
this.showMessage('SDK未初始化,请先初始化', 'error');
|
|
340
|
+
break;
|
|
341
|
+
case OperationErrorCode.AVATAR_NOT_LOADED:
|
|
342
|
+
this.showMessage('数字人未加载,请先加载数字人', 'error');
|
|
343
|
+
break;
|
|
344
|
+
default:
|
|
345
|
+
this.showMessage(`操作失败: ${error.message}`, 'error');
|
|
346
|
+
}
|
|
347
|
+
} else {
|
|
348
|
+
this.showMessage(`系统错误: ${error.message}`, 'error');
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// UI相关方法
|
|
353
|
+
setupUI() {
|
|
354
|
+
// 设置UI事件监听器
|
|
355
|
+
document.getElementById('init-btn').addEventListener('click', () => this.initSDK());
|
|
356
|
+
document.getElementById('play-motion-btn').addEventListener('click', () => this.playMotion('wave_hand'));
|
|
357
|
+
document.getElementById('speak-btn').addEventListener('click', () => {
|
|
358
|
+
const text = document.getElementById('text-input').value;
|
|
359
|
+
this.speakText(text);
|
|
360
|
+
});
|
|
361
|
+
document.getElementById('pause-btn').addEventListener('click', () => this.pauseBroadcast());
|
|
362
|
+
document.getElementById('resume-btn').addEventListener('click', () => this.resumeBroadcast());
|
|
363
|
+
document.getElementById('stop-btn').addEventListener('click', () => this.stopBroadcast());
|
|
364
|
+
|
|
365
|
+
// 摄像机切换
|
|
366
|
+
document.getElementById('camera-whole').addEventListener('click', () => this.setCamera(AvatarCameraType.WHOLE));
|
|
367
|
+
document.getElementById('camera-half').addEventListener('click', () => this.setCamera(AvatarCameraType.HALF));
|
|
368
|
+
document.getElementById('camera-face').addEventListener('click', () => this.setCamera(AvatarCameraType.FACE));
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
updateUI() {
|
|
372
|
+
// 更新UI状态
|
|
373
|
+
document.getElementById('init-btn').disabled = this.isInitialized;
|
|
374
|
+
document.getElementById('play-motion-btn').disabled = !this.isInitialized;
|
|
375
|
+
document.getElementById('speak-btn').disabled = !this.isInitialized;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
updateProgressBar(percent) {
|
|
379
|
+
const progressBar = document.getElementById('progress-bar');
|
|
380
|
+
if (progressBar) {
|
|
381
|
+
progressBar.style.width = `${percent}%`;
|
|
382
|
+
progressBar.textContent = `${percent}%`;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
showMessage(message, type = 'info') {
|
|
387
|
+
const messageDiv = document.getElementById('message');
|
|
388
|
+
if (messageDiv) {
|
|
389
|
+
messageDiv.textContent = message;
|
|
390
|
+
messageDiv.className = `message ${type}`;
|
|
391
|
+
setTimeout(() => {
|
|
392
|
+
messageDiv.textContent = '';
|
|
393
|
+
messageDiv.className = 'message';
|
|
394
|
+
}, 5000);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// 清理资源
|
|
399
|
+
destroy() {
|
|
400
|
+
if (this.sdk) {
|
|
401
|
+
this.sdk.destroy();
|
|
402
|
+
this.sdk = null;
|
|
403
|
+
this.isInitialized = false;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// 创建应用实例
|
|
409
|
+
const app = new AvatarApp();
|
|
410
|
+
|
|
411
|
+
// 页面卸载时清理
|
|
412
|
+
window.addEventListener('beforeunload', () => {
|
|
413
|
+
app.destroy();
|
|
414
|
+
});
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## 📚 API 参考
|
|
418
|
+
|
|
419
|
+
### ZEEAvatarSDK 类
|
|
420
|
+
|
|
421
|
+
#### 构造函数
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
constructor(config: IAvatarSDKConfig)
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
创建SDK实例,需要传入完整的配置对象。
|
|
428
|
+
|
|
429
|
+
**参数说明:**
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
interface IAvatarSDKConfig {
|
|
433
|
+
// Unity构建文件配置(必填)
|
|
434
|
+
loaderUrl: string; // Unity加载器脚本URL
|
|
435
|
+
dataUrl: string; // Unity数据文件URL
|
|
436
|
+
frameworkUrl: string; // Unity框架文件URL
|
|
437
|
+
codeUrl: string; // Unity代码文件URL
|
|
438
|
+
|
|
439
|
+
// 基础配置
|
|
440
|
+
containerId?: string; // 容器DOM元素ID,默认'unity-container'
|
|
441
|
+
token?: string; // 用户认证令牌
|
|
442
|
+
env?: 'dev' | 'test' | 'prod' | 'custom'; // 运行环境,默认'prod'
|
|
443
|
+
apiUrl?: string; // 自定义API地址(env='custom'时需要)
|
|
444
|
+
resourcesUrl?: string; // AB资源文件地址
|
|
445
|
+
idleMotionList?:string[]; // 待机动作编码列表,随机播放(排重方式),可选
|
|
446
|
+
// 回调函数
|
|
447
|
+
onProgress?: (progress: number) => void; // 加载进度回调
|
|
448
|
+
}
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
#### 核心方法
|
|
452
|
+
|
|
453
|
+
##### initializeAvatar()
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
async initializeAvatar(
|
|
457
|
+
avatarCode: string,
|
|
458
|
+
cameraType?: AvatarCameraType
|
|
459
|
+
): Promise<IAvatarCallbackResponse>
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
初始化数字人,这是使用SDK的第一步,会自动完成Unity环境初始化和数字人加载。
|
|
463
|
+
|
|
464
|
+
**参数:**
|
|
465
|
+
- `avatarCode`: 数字人编码(必填)
|
|
466
|
+
- `cameraType`: 摄像机类型,可选值:
|
|
467
|
+
- `AvatarCameraType.WHOLE` - 全身视角(默认)
|
|
468
|
+
- `AvatarCameraType.HALF` - 半身视角
|
|
469
|
+
- `AvatarCameraType.FACE` - 面部视角
|
|
470
|
+
|
|
471
|
+
**返回值:**
|
|
472
|
+
```typescript
|
|
473
|
+
interface IAvatarCallbackResponse {
|
|
474
|
+
success: boolean; // 操作是否成功
|
|
475
|
+
message: string; // 响应消息
|
|
476
|
+
errorCode?: number; // 错误代码(可选)
|
|
477
|
+
data?: any; // 返回数据(可选)
|
|
478
|
+
}
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
**使用示例:**
|
|
482
|
+
```javascript
|
|
483
|
+
try {
|
|
484
|
+
const response = await sdk.initializeAvatar('avatar001', AvatarCameraType.WHOLE);
|
|
485
|
+
if (response.success) {
|
|
486
|
+
console.log('数字人初始化成功');
|
|
487
|
+
}
|
|
488
|
+
} catch (error) {
|
|
489
|
+
console.error('初始化失败:', error);
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
##### playMotion()
|
|
494
|
+
|
|
495
|
+
```typescript
|
|
496
|
+
async playMotion(clipCode: string): Promise<IAvatarCallbackResponse>
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
播放数字人动作。
|
|
500
|
+
|
|
501
|
+
**参数:**
|
|
502
|
+
- `clipCode`: 动作编码(必填)
|
|
503
|
+
|
|
504
|
+
**使用示例:**
|
|
505
|
+
```javascript
|
|
506
|
+
try {
|
|
507
|
+
const response = await sdk.playMotion('wave_hand');
|
|
508
|
+
if (response.success) {
|
|
509
|
+
console.log('动作播放成功');
|
|
510
|
+
}
|
|
511
|
+
} catch (error) {
|
|
512
|
+
console.error('动作播放失败:', error);
|
|
513
|
+
}
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
##### getCurrentMotion()
|
|
517
|
+
|
|
518
|
+
```typescript
|
|
519
|
+
async getCurrentMotion(getRemainingTime?: boolean): Promise<IAvatarCallbackResponse>
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
获取当前播放的动作信息。
|
|
523
|
+
|
|
524
|
+
**参数:**
|
|
525
|
+
- `getRemainingTime`: 是否获取剩余时间,默认false
|
|
526
|
+
|
|
527
|
+
**返回值:**
|
|
528
|
+
```typescript
|
|
529
|
+
interface IAvatarCallbackResponse {
|
|
530
|
+
success: boolean;
|
|
531
|
+
message: string;
|
|
532
|
+
data?: {
|
|
533
|
+
motionId?: string; // 动作ID
|
|
534
|
+
motionRemainingTime?: number; // 动作剩余时间(秒)
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
**使用示例:**
|
|
540
|
+
```javascript
|
|
541
|
+
// 获取动作编码和剩余时间
|
|
542
|
+
const response = await sdk.getCurrentMotion(true);
|
|
543
|
+
if (response.success) {
|
|
544
|
+
console.log('动作编码:', response.data.motionId);
|
|
545
|
+
console.log('剩余时间:', response.data.motionRemainingTime);
|
|
546
|
+
}
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
##### setCamera()
|
|
550
|
+
|
|
551
|
+
```typescript
|
|
552
|
+
async setCamera(cameraType: AvatarCameraType): Promise<IAvatarCallbackResponse>
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
设置摄像机类型。
|
|
556
|
+
|
|
557
|
+
**参数:**
|
|
558
|
+
- `cameraType`: 摄像机类型
|
|
559
|
+
|
|
560
|
+
**使用示例:**
|
|
561
|
+
```javascript
|
|
562
|
+
await sdk.setCamera(AvatarCameraType.FACE);
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
##### unloadAvatar()
|
|
566
|
+
|
|
567
|
+
```typescript
|
|
568
|
+
async unloadAvatar(): Promise<IAvatarCallbackResponse>
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
卸载数字人,释放数字人相关资源。
|
|
572
|
+
|
|
573
|
+
**使用示例:**
|
|
574
|
+
```javascript
|
|
575
|
+
try {
|
|
576
|
+
const response = await sdk.unloadAvatar();
|
|
577
|
+
if (response.success) {
|
|
578
|
+
console.log('数字人卸载成功');
|
|
579
|
+
}
|
|
580
|
+
} catch (error) {
|
|
581
|
+
console.error('卸载失败:', error);
|
|
582
|
+
}
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
#### 播报相关方法
|
|
586
|
+
|
|
587
|
+
##### startBroadcast()
|
|
588
|
+
|
|
589
|
+
```typescript
|
|
590
|
+
async startBroadcast(params: IBroadcastParams): Promise<void>
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
开始播报,支持文本转语音和音频播报两种模式。
|
|
594
|
+
|
|
595
|
+
**参数:**
|
|
596
|
+
```typescript
|
|
597
|
+
interface IBroadcastParams {
|
|
598
|
+
type: BroadcastType; // 播报类型:'text' | 'audio'
|
|
599
|
+
humanCode: string; // 数字人编码
|
|
600
|
+
text?: string; // 播报文本(文本播报必填)
|
|
601
|
+
audioUrl?: string; // 音频URL(音频播报必填)
|
|
602
|
+
voiceCode?: string; // 音色编码(文本播报必填)
|
|
603
|
+
speed?: number; // 语速(0.5-2.0),默认1.0
|
|
604
|
+
volume: number; // 音量(0-1.0)
|
|
605
|
+
isSubtitle: boolean; // 是否显示字幕
|
|
606
|
+
motionList:string[]; // 播报过程中才播放的动作集合,每个动作间隔2-3秒循环播放,播报顺序根据`motionPlayMode`参数处理,默认为`随机`,可选
|
|
607
|
+
motionPlayMode?: 'random' | 'sequence'; // 动作播放模式,随机、顺序,随机=`random`,顺序=`sequence`
|
|
608
|
+
}
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
**使用示例:**
|
|
612
|
+
```javascript
|
|
613
|
+
// 文本播报
|
|
614
|
+
await sdk.startBroadcast({
|
|
615
|
+
type: BroadcastType.TEXT,
|
|
616
|
+
humanCode: 'avatar001',
|
|
617
|
+
text: '欢迎使用ZEE 3D Avatar SDK',
|
|
618
|
+
voiceCode: 'VOICE001',
|
|
619
|
+
volume: 1.0,
|
|
620
|
+
speed: 1.0,
|
|
621
|
+
isSubtitle: false
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
// 音频播报
|
|
625
|
+
await sdk.startBroadcast({
|
|
626
|
+
type: BroadcastType.AUDIO,
|
|
627
|
+
humanCode: 'avatar001',
|
|
628
|
+
audioUrl: 'https://example.com/audio.mp3',
|
|
629
|
+
text: '音频字幕内容',
|
|
630
|
+
volume: 1.0,
|
|
631
|
+
isSubtitle: true
|
|
632
|
+
});
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
##### pauseBroadcast()
|
|
636
|
+
|
|
637
|
+
```typescript
|
|
638
|
+
async pauseBroadcast(resetIdle?:boolean): Promise<void>
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
暂停当前播报。
|
|
642
|
+
|
|
643
|
+
**参数**
|
|
644
|
+
|
|
645
|
+
- `resetIdle`: 动作和口型是否回到待机状态,默认为false
|
|
646
|
+
|
|
647
|
+
##### resumeBroadcast()
|
|
648
|
+
|
|
649
|
+
```typescript
|
|
650
|
+
async resumeBroadcast(): Promise<void>
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
恢复播报。
|
|
654
|
+
|
|
655
|
+
##### stopBroadcast()
|
|
656
|
+
|
|
657
|
+
```typescript
|
|
658
|
+
async stopBroadcast(): Promise<void>
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
停止播报。
|
|
662
|
+
|
|
663
|
+
##### updateBroadcastCallbacks()
|
|
664
|
+
|
|
665
|
+
```typescript
|
|
666
|
+
updateBroadcastCallbacks(callbacks: IBroadcastCallbacks): void
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
更新播报回调函数。
|
|
670
|
+
|
|
671
|
+
**参数:**
|
|
672
|
+
```typescript
|
|
673
|
+
interface IBroadcastCallbacks {
|
|
674
|
+
onStart?: () => void; // 播报开始
|
|
675
|
+
onFinish?: () => void; // 播报完成
|
|
676
|
+
onError?: (error: Error) => void; // 播报错误
|
|
677
|
+
onPause?: () => void; // 播报暂停
|
|
678
|
+
onResume?: () => void; // 播报恢复
|
|
679
|
+
onStop?: () => void; // 播报停止
|
|
680
|
+
onAbort?: () => void; // 播报中断
|
|
681
|
+
}
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
**使用示例:**
|
|
685
|
+
```javascript
|
|
686
|
+
sdk.updateBroadcastCallbacks({
|
|
687
|
+
onStart: () => console.log('播报开始'),
|
|
688
|
+
onFinish: () => console.log('播报完成'),
|
|
689
|
+
onError: (error) => console.error('播报错误:', error)
|
|
690
|
+
});
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
##### getBroadcastStatus()
|
|
694
|
+
|
|
695
|
+
```typescript
|
|
696
|
+
getBroadcastStatus(): {
|
|
697
|
+
isActive: boolean;
|
|
698
|
+
isGeneratingAudio: boolean;
|
|
699
|
+
hasReceivedAudio: boolean;
|
|
700
|
+
pendingCallbacks: number;
|
|
701
|
+
hasController: boolean;
|
|
702
|
+
}
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
获取播报状态信息。
|
|
706
|
+
|
|
707
|
+
#### 工具方法
|
|
708
|
+
|
|
709
|
+
##### updateToken()
|
|
710
|
+
|
|
711
|
+
```typescript
|
|
712
|
+
updateToken(token: string): void
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
更新认证Token。
|
|
716
|
+
|
|
717
|
+
##### getInstanceId()
|
|
718
|
+
|
|
719
|
+
```typescript
|
|
720
|
+
getInstanceId(): string
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
获取SDK实例的唯一标识符。
|
|
724
|
+
|
|
725
|
+
##### isSDKInitialized()
|
|
726
|
+
|
|
727
|
+
```typescript
|
|
728
|
+
isSDKInitialized(): boolean
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
检查SDK是否已初始化。
|
|
732
|
+
|
|
733
|
+
##### isAvatarInitialized()
|
|
734
|
+
|
|
735
|
+
```typescript
|
|
736
|
+
isAvatarInitialized(): boolean
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
检查数字人是否已加载。
|
|
740
|
+
|
|
741
|
+
##### getConfig()
|
|
742
|
+
|
|
743
|
+
```typescript
|
|
744
|
+
getConfig(): IAvatarSDKConfig
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
获取当前SDK配置。
|
|
748
|
+
|
|
749
|
+
##### destroy()
|
|
750
|
+
|
|
751
|
+
```typescript
|
|
752
|
+
destroy(): void
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
销毁SDK实例,清理所有资源。**重要:页面卸载前务必调用此方法!**
|
|
756
|
+
|
|
757
|
+
## 🔧 高级功能
|
|
758
|
+
|
|
759
|
+
### 多实例支持
|
|
760
|
+
|
|
761
|
+
新版SDK支持在同一页面创建多个独立的SDK实例,每个实例拥有独立的回调函数命名空间,避免冲突。
|
|
762
|
+
|
|
763
|
+
```javascript
|
|
764
|
+
// 创建多个SDK实例
|
|
765
|
+
const sdk1 = new ZEEAvatarSDK({
|
|
766
|
+
loaderUrl: './assets/Build/webgl.loader.js',
|
|
767
|
+
dataUrl: './assets/Build/webgl.data.unityweb',
|
|
768
|
+
frameworkUrl: './assets/Build/webgl.framework.js.unityweb',
|
|
769
|
+
codeUrl: './assets/Build/webgl.wasm.unityweb',
|
|
770
|
+
containerId: 'unity-container-1',
|
|
771
|
+
token: 'token1'
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
const sdk2 = new ZEEAvatarSDK({
|
|
775
|
+
loaderUrl: './assets/Build/webgl.loader.js',
|
|
776
|
+
dataUrl: './assets/Build/webgl.data.unityweb',
|
|
777
|
+
frameworkUrl: './assets/Build/webgl.framework.js.unityweb',
|
|
778
|
+
codeUrl: './assets/Build/webgl.wasm.unityweb',
|
|
779
|
+
containerId: 'unity-container-2',
|
|
780
|
+
token: 'token2'
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
// 分别初始化不同的数字人
|
|
784
|
+
await sdk1.initializeAvatar('avatar001');
|
|
785
|
+
await sdk2.initializeAvatar('avatar002');
|
|
786
|
+
|
|
787
|
+
// 独立控制
|
|
788
|
+
await sdk1.playMotion('wave_hand');
|
|
789
|
+
await sdk2.playMotion('bow');
|
|
790
|
+
|
|
791
|
+
// 清理资源
|
|
792
|
+
sdk1.destroy();
|
|
793
|
+
sdk2.destroy();
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
### 错误处理最佳实践
|
|
797
|
+
|
|
798
|
+
```javascript
|
|
799
|
+
import {
|
|
800
|
+
SDKError,
|
|
801
|
+
NetworkErrorCode,
|
|
802
|
+
OperationErrorCode,
|
|
803
|
+
ResourceErrorCode,
|
|
804
|
+
SystemErrorCode,
|
|
805
|
+
ConfigErrorCode
|
|
806
|
+
} from '@zeewain/3d-avatar-sdk'
|
|
807
|
+
|
|
808
|
+
// 统一错误处理函数
|
|
809
|
+
function handleSDKError(error) {
|
|
810
|
+
if (error instanceof SDKError) {
|
|
811
|
+
console.error(`SDK错误 [${error.code}]: ${error.message}`);
|
|
812
|
+
|
|
813
|
+
// 根据错误类别处理
|
|
814
|
+
switch (error.category) {
|
|
815
|
+
case 'NETWORK':
|
|
816
|
+
handleNetworkError(error);
|
|
817
|
+
break;
|
|
818
|
+
case 'OPERATION':
|
|
819
|
+
handleOperationError(error);
|
|
820
|
+
break;
|
|
821
|
+
case 'RESOURCE':
|
|
822
|
+
handleResourceError(error);
|
|
823
|
+
break;
|
|
824
|
+
case 'SYSTEM':
|
|
825
|
+
handleSystemError(error);
|
|
826
|
+
break;
|
|
827
|
+
case 'CONFIG':
|
|
828
|
+
handleConfigError(error);
|
|
829
|
+
break;
|
|
830
|
+
}
|
|
831
|
+
} else {
|
|
832
|
+
console.error('系统错误:', error);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
// 网络错误处理
|
|
837
|
+
function handleNetworkError(error) {
|
|
838
|
+
switch (error.code) {
|
|
839
|
+
case NetworkErrorCode.CONNECTION_FAILED:
|
|
840
|
+
showUserMessage('网络连接失败,请检查网络状态');
|
|
841
|
+
break;
|
|
842
|
+
case NetworkErrorCode.UNAUTHORIZED:
|
|
843
|
+
showUserMessage('认证失效,请重新登录');
|
|
844
|
+
// 可以触发重新登录流程
|
|
845
|
+
redirectToLogin();
|
|
846
|
+
break;
|
|
847
|
+
case NetworkErrorCode.REQUEST_TIMEOUT:
|
|
848
|
+
showUserMessage('请求超时,请稍后重试');
|
|
849
|
+
break;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// 操作错误处理
|
|
854
|
+
function handleOperationError(error) {
|
|
855
|
+
switch (error.code) {
|
|
856
|
+
case OperationErrorCode.UNITY_NOT_INITIALIZED:
|
|
857
|
+
showUserMessage('系统未初始化,请稍后重试');
|
|
858
|
+
break;
|
|
859
|
+
case OperationErrorCode.AVATAR_NOT_LOADED:
|
|
860
|
+
showUserMessage('数字人未加载,请先加载数字人');
|
|
861
|
+
break;
|
|
862
|
+
case OperationErrorCode.OPERATION_TIMEOUT:
|
|
863
|
+
showUserMessage('操作超时,请稍后重试');
|
|
864
|
+
break;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
// 在SDK操作中使用
|
|
869
|
+
try {
|
|
870
|
+
await sdk.initializeAvatar('avatar001');
|
|
871
|
+
} catch (error) {
|
|
872
|
+
handleSDKError(error);
|
|
873
|
+
}
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
### 性能优化建议
|
|
877
|
+
|
|
878
|
+
#### 1. 资源预加载
|
|
879
|
+
|
|
880
|
+
```javascript
|
|
881
|
+
// 预加载Unity资源
|
|
882
|
+
const preloadPromise = fetch('./assets/Build/webgl.data.unityweb', {
|
|
883
|
+
method: 'HEAD'
|
|
884
|
+
});
|
|
885
|
+
|
|
886
|
+
// 在需要时再创建SDK实例
|
|
887
|
+
preloadPromise.then(() => {
|
|
888
|
+
const sdk = new ZEEAvatarSDK(config);
|
|
889
|
+
sdk.initializeAvatar('avatar001');
|
|
890
|
+
});
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
#### 2. 懒加载策略
|
|
894
|
+
|
|
895
|
+
```javascript
|
|
896
|
+
class LazyAvatarLoader {
|
|
897
|
+
constructor() {
|
|
898
|
+
this.sdk = null;
|
|
899
|
+
this.isLoading = false;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
async loadWhenNeeded() {
|
|
903
|
+
if (this.sdk || this.isLoading) return;
|
|
904
|
+
|
|
905
|
+
this.isLoading = true;
|
|
906
|
+
try {
|
|
907
|
+
this.sdk = new ZEEAvatarSDK(config);
|
|
908
|
+
await this.sdk.initializeAvatar('avatar001');
|
|
909
|
+
} finally {
|
|
910
|
+
this.isLoading = false;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
async speak(text) {
|
|
915
|
+
await this.loadWhenNeeded();
|
|
916
|
+
return this.sdk.startBroadcast({
|
|
917
|
+
type: BroadcastType.TEXT,
|
|
918
|
+
humanCode: 'avatar001',
|
|
919
|
+
text: text,
|
|
920
|
+
voiceCode: 'VOICE001',
|
|
921
|
+
volume: 1.0,
|
|
922
|
+
isSubtitle: false
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
```
|
|
927
|
+
|
|
928
|
+
#### 3. 内存管理
|
|
929
|
+
|
|
930
|
+
```javascript
|
|
931
|
+
class AvatarManager {
|
|
932
|
+
constructor() {
|
|
933
|
+
this.sdk = null;
|
|
934
|
+
this.isActive = false;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
async initialize() {
|
|
938
|
+
if (this.sdk) return;
|
|
939
|
+
|
|
940
|
+
this.sdk = new ZEEAvatarSDK(config);
|
|
941
|
+
await this.sdk.initializeAvatar('avatar001');
|
|
942
|
+
this.isActive = true;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
async pause() {
|
|
946
|
+
if (this.sdk && this.isActive) {
|
|
947
|
+
await this.sdk.unloadAvatar();
|
|
948
|
+
this.isActive = false;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
async resume() {
|
|
953
|
+
if (this.sdk && !this.isActive) {
|
|
954
|
+
await this.sdk.initializeAvatar('avatar001');
|
|
955
|
+
this.isActive = true;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
destroy() {
|
|
960
|
+
if (this.sdk) {
|
|
961
|
+
this.sdk.destroy();
|
|
962
|
+
this.sdk = null;
|
|
963
|
+
this.isActive = false;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// 页面可见性变化时管理资源
|
|
969
|
+
const avatarManager = new AvatarManager();
|
|
970
|
+
|
|
971
|
+
document.addEventListener('visibilitychange', () => {
|
|
972
|
+
if (document.hidden) {
|
|
973
|
+
avatarManager.pause();
|
|
974
|
+
} else {
|
|
975
|
+
avatarManager.resume();
|
|
976
|
+
}
|
|
977
|
+
});
|
|
978
|
+
```
|
|
979
|
+
|
|
980
|
+
## 🚨 错误码参考
|
|
981
|
+
|
|
982
|
+
### 网络错误 (1xxx)
|
|
983
|
+
| 错误码 | 常量名 | 描述 | 处理建议 |
|
|
984
|
+
|:------:|:-------|:-----|:---------|
|
|
985
|
+
| 1001 | `NetworkErrorCode.CONNECTION_FAILED` | 网络连接失败 | 检查网络状态,重试连接 |
|
|
986
|
+
| 1002 | `NetworkErrorCode.REQUEST_TIMEOUT` | 请求超时 | 检查网络延迟,稍后重试 |
|
|
987
|
+
| 1003 | `NetworkErrorCode.SERVER_ERROR` | 服务器错误 | 联系技术支持 |
|
|
988
|
+
| 1004 | `NetworkErrorCode.UNAUTHORIZED` | 未授权访问 | 更新Token或重新登录 |
|
|
989
|
+
|
|
990
|
+
### 操作错误 (2xxx)
|
|
991
|
+
| 错误码 | 常量名 | 描述 | 处理建议 |
|
|
992
|
+
|:------:|:-------|:-----|:---------|
|
|
993
|
+
| 2001 | `OperationErrorCode.UNITY_NOT_INITIALIZED` | Unity实例未初始化 | 先调用initializeAvatar() |
|
|
994
|
+
| 2002 | `OperationErrorCode.AVATAR_NOT_LOADED` | 数字人未加载 | 确保数字人已成功加载 |
|
|
995
|
+
| 2003 | `OperationErrorCode.OPERATION_FAILED` | 操作执行失败 | 检查参数和网络状态 |
|
|
996
|
+
| 2004 | `OperationErrorCode.OPERATION_TIMEOUT` | 操作超时 | 稍后重试 |
|
|
997
|
+
| 2005 | `OperationErrorCode.OPERATION_CANCELLED` | 操作被取消 | 重新执行操作 |
|
|
998
|
+
|
|
999
|
+
### 资源错误 (3xxx)
|
|
1000
|
+
| 错误码 | 常量名 | 描述 | 处理建议 |
|
|
1001
|
+
|:------:|:-------|:-----|:---------|
|
|
1002
|
+
| 3001 | `ResourceErrorCode.LOAD_FAILED` | 资源加载失败 | 检查资源URL和网络 |
|
|
1003
|
+
| 3002 | `ResourceErrorCode.FILE_CORRUPTED` | 资源文件损坏 | 重新下载资源文件 |
|
|
1004
|
+
| 3003 | `ResourceErrorCode.NOT_FOUND` | 资源不存在 | 检查资源路径 |
|
|
1005
|
+
| 3004 | `ResourceErrorCode.UNSUPPORTED_FORMAT` | 资源格式不支持 | 使用支持的格式 |
|
|
1006
|
+
|
|
1007
|
+
### 系统错误 (4xxx)
|
|
1008
|
+
| 错误码 | 常量名 | 描述 | 处理建议 |
|
|
1009
|
+
|:------:|:-------|:-----|:---------|
|
|
1010
|
+
| 4001 | `SystemErrorCode.OUT_OF_MEMORY` | 内存不足 | 关闭其他应用,释放内存 |
|
|
1011
|
+
| 4002 | `SystemErrorCode.GPU_NOT_SUPPORTED` | GPU不支持 | 更新显卡驱动 |
|
|
1012
|
+
| 4003 | `SystemErrorCode.WEBGL_NOT_SUPPORTED` | WebGL不支持 | 更新浏览器 |
|
|
1013
|
+
| 4004 | `SystemErrorCode.BROWSER_NOT_COMPATIBLE` | 浏览器不兼容 | 使用推荐浏览器 |
|
|
1014
|
+
|
|
1015
|
+
### 配置错误 (5xxx)
|
|
1016
|
+
| 错误码 | 常量名 | 描述 | 处理建议 |
|
|
1017
|
+
|:------:|:-------|:-----|:---------|
|
|
1018
|
+
| 5001 | `ConfigErrorCode.INVALID_CONFIG` | 配置参数无效 | 检查配置格式 |
|
|
1019
|
+
| 5002 | `ConfigErrorCode.MISSING_REQUIRED_PARAM` | 必需参数缺失 | 补充必需参数 |
|
|
1020
|
+
| 5003 | `ConfigErrorCode.PARAM_OUT_OF_RANGE` | 参数值超出范围 | 调整参数值 |
|
|
1021
|
+
| 5004 | `ConfigErrorCode.INVALID_JSON_FORMAT` | JSON格式错误 | 检查JSON格式 |
|
|
1022
|
+
|
|
1023
|
+
## 🌍 浏览器兼容性
|
|
1024
|
+
|
|
1025
|
+
### 支持的浏览器版本
|
|
1026
|
+
|
|
1027
|
+
| 浏览器 | 最低版本 | 推荐版本 | 备注 |
|
|
1028
|
+
|:-------|:---------|:---------|:-----|
|
|
1029
|
+
| **Chrome** | 60+ | 90+ | 最佳性能 |
|
|
1030
|
+
| **Firefox** | 55+ | 85+ | 良好支持 |
|
|
1031
|
+
| **Safari** | 10.1+ | 14+ | 需要WebGL 2.0 |
|
|
1032
|
+
| **Edge** | 16+ | 90+ | 基于Chromium |
|
|
1033
|
+
| **IE** | 11 | - | 需要ES5版本 |
|
|
1034
|
+
|
|
1035
|
+
### 模块系统兼容性
|
|
1036
|
+
|
|
1037
|
+
```javascript
|
|
1038
|
+
// 现代浏览器 (ES6+)
|
|
1039
|
+
import { ZEEAvatarSDK } from '@zeewain/3d-avatar-sdk'
|
|
1040
|
+
|
|
1041
|
+
// IE11 兼容
|
|
1042
|
+
import { ZEEAvatarSDK } from '@zeewain/3d-avatar-sdk/es5'
|
|
1043
|
+
|
|
1044
|
+
// CommonJS (Node.js)
|
|
1045
|
+
const { ZEEAvatarSDK } = require('@zeewain/3d-avatar-sdk')
|
|
1046
|
+
```
|
|
1047
|
+
|
|
1048
|
+
### 功能检测
|
|
1049
|
+
|
|
1050
|
+
```javascript
|
|
1051
|
+
// 检查WebGL支持
|
|
1052
|
+
function checkWebGLSupport() {
|
|
1053
|
+
try {
|
|
1054
|
+
const canvas = document.createElement('canvas');
|
|
1055
|
+
const gl = canvas.getContext('webgl2') || canvas.getContext('webgl');
|
|
1056
|
+
return !!gl;
|
|
1057
|
+
} catch (e) {
|
|
1058
|
+
return false;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
// 检查浏览器兼容性
|
|
1063
|
+
function checkBrowserCompatibility() {
|
|
1064
|
+
const checks = {
|
|
1065
|
+
webgl: checkWebGLSupport(),
|
|
1066
|
+
promise: typeof Promise !== 'undefined',
|
|
1067
|
+
fetch: typeof fetch !== 'undefined',
|
|
1068
|
+
es6: typeof Symbol !== 'undefined'
|
|
1069
|
+
};
|
|
1070
|
+
|
|
1071
|
+
return checks;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// 使用检测结果
|
|
1075
|
+
const compatibility = checkBrowserCompatibility();
|
|
1076
|
+
if (!compatibility.webgl) {
|
|
1077
|
+
console.error('浏览器不支持WebGL');
|
|
1078
|
+
}
|
|
1079
|
+
```
|
|
1080
|
+
|
|
1081
|
+
## 📋 最佳实践
|
|
1082
|
+
|
|
1083
|
+
### 1. 生命周期管理
|
|
1084
|
+
|
|
1085
|
+
```javascript
|
|
1086
|
+
class AvatarComponent {
|
|
1087
|
+
constructor() {
|
|
1088
|
+
this.sdk = null;
|
|
1089
|
+
this.isDestroyed = false;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
async mount() {
|
|
1093
|
+
if (this.isDestroyed) return;
|
|
1094
|
+
|
|
1095
|
+
this.sdk = new ZEEAvatarSDK(config);
|
|
1096
|
+
|
|
1097
|
+
// 设置错误处理
|
|
1098
|
+
this.setupErrorHandling();
|
|
1099
|
+
|
|
1100
|
+
// 初始化数字人
|
|
1101
|
+
await this.sdk.initializeAvatar('avatar001');
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
async unmount() {
|
|
1105
|
+
this.isDestroyed = true;
|
|
1106
|
+
|
|
1107
|
+
if (this.sdk) {
|
|
1108
|
+
try {
|
|
1109
|
+
await this.sdk.unloadAvatar();
|
|
1110
|
+
} catch (error) {
|
|
1111
|
+
console.warn('卸载数字人时出错:', error);
|
|
1112
|
+
} finally {
|
|
1113
|
+
this.sdk.destroy();
|
|
1114
|
+
this.sdk = null;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
setupErrorHandling() {
|
|
1120
|
+
// 全局错误处理
|
|
1121
|
+
window.addEventListener('error', (event) => {
|
|
1122
|
+
if (event.error && event.error.name === 'SDKError') {
|
|
1123
|
+
this.handleSDKError(event.error);
|
|
1124
|
+
}
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
```
|
|
1129
|
+
|
|
1130
|
+
### 2. 状态管理
|
|
1131
|
+
|
|
1132
|
+
```javascript
|
|
1133
|
+
class AvatarState {
|
|
1134
|
+
constructor() {
|
|
1135
|
+
this.state = {
|
|
1136
|
+
isInitialized: false,
|
|
1137
|
+
isLoading: false,
|
|
1138
|
+
isSpeaking: false,
|
|
1139
|
+
currentMotion: null,
|
|
1140
|
+
error: null
|
|
1141
|
+
};
|
|
1142
|
+
|
|
1143
|
+
this.listeners = [];
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
setState(newState) {
|
|
1147
|
+
this.state = { ...this.state, ...newState };
|
|
1148
|
+
this.notifyListeners();
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
subscribe(listener) {
|
|
1152
|
+
this.listeners.push(listener);
|
|
1153
|
+
return () => {
|
|
1154
|
+
this.listeners = this.listeners.filter(l => l !== listener);
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
notifyListeners() {
|
|
1159
|
+
this.listeners.forEach(listener => listener(this.state));
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
// 使用状态管理
|
|
1164
|
+
const avatarState = new AvatarState();
|
|
1165
|
+
|
|
1166
|
+
avatarState.subscribe((state) => {
|
|
1167
|
+
console.log('状态变化:', state);
|
|
1168
|
+
updateUI(state);
|
|
1169
|
+
});
|
|
1170
|
+
```
|
|
1171
|
+
|
|
1172
|
+
### 3. 配置管理
|
|
1173
|
+
|
|
1174
|
+
```javascript
|
|
1175
|
+
// 配置文件 config.js
|
|
1176
|
+
export const avatarConfig = {
|
|
1177
|
+
development: {
|
|
1178
|
+
loaderUrl: './assets/Build/webgl.loader.js',
|
|
1179
|
+
dataUrl: './assets/Build/webgl.data.unityweb',
|
|
1180
|
+
frameworkUrl: './assets/Build/webgl.framework.js.unityweb',
|
|
1181
|
+
codeUrl: './assets/Build/webgl.wasm.unityweb',
|
|
1182
|
+
containerId: 'unity-container',
|
|
1183
|
+
env: 'dev',
|
|
1184
|
+
token: 'dev-token'
|
|
1185
|
+
},
|
|
1186
|
+
production: {
|
|
1187
|
+
loaderUrl: 'https://cdn.example.com/webgl.loader.js',
|
|
1188
|
+
dataUrl: 'https://cdn.example.com/webgl.data.unityweb',
|
|
1189
|
+
frameworkUrl: 'https://cdn.example.com/webgl.framework.js.unityweb',
|
|
1190
|
+
codeUrl: 'https://cdn.example.com/webgl.wasm.unityweb',
|
|
1191
|
+
containerId: 'unity-container',
|
|
1192
|
+
env: 'prod',
|
|
1193
|
+
token: process.env.AVATAR_TOKEN
|
|
1194
|
+
}
|
|
1195
|
+
};
|
|
1196
|
+
|
|
1197
|
+
// 使用配置
|
|
1198
|
+
const config = avatarConfig[process.env.NODE_ENV || 'development'];
|
|
1199
|
+
const sdk = new ZEEAvatarSDK(config);
|
|
1200
|
+
```
|
|
1201
|
+
|
|
1202
|
+
## 🔄 从旧版本迁移
|
|
1203
|
+
|
|
1204
|
+
### 主要变化
|
|
1205
|
+
|
|
1206
|
+
| 旧版本 | 新版本 | 变化说明 |
|
|
1207
|
+
|:-------|:-------|:---------|
|
|
1208
|
+
| 多个类 | 单个类 | `ZEEAvatarLoader` + `AvatarService` + `BroadcastService` → `ZEEAvatarSDK` |
|
|
1209
|
+
| 分步初始化 | 统一初始化 | `init()` + `initializeAvatar()` → `initializeAvatar()` |
|
|
1210
|
+
| 手动管理 | 自动管理 | 内部自动管理各个服务实例 |
|
|
1211
|
+
| 回调冲突 | 回调隔离 | 支持多实例,回调函数完全隔离 |
|
|
1212
|
+
| 暴露内部 | 封装内部 | 移除 `getUnityInstance()` 等内部方法 |
|
|
1213
|
+
|
|
1214
|
+
### 迁移示例
|
|
1215
|
+
|
|
1216
|
+
**旧版本代码:**
|
|
1217
|
+
```javascript
|
|
1218
|
+
// 旧版本需要创建多个实例
|
|
1219
|
+
const loader = new ZEEAvatarLoader(config);
|
|
1220
|
+
const avatarAPI = await loader.init();
|
|
1221
|
+
const broadcastService = new BroadcastService({
|
|
1222
|
+
unityInstance: loader.getInstance(),
|
|
1223
|
+
callbacks: { /* ... */ }
|
|
1224
|
+
});
|
|
1225
|
+
|
|
1226
|
+
// 分步初始化
|
|
1227
|
+
await avatarAPI.initializeAvatar('avatar001', 'whole');
|
|
1228
|
+
```
|
|
1229
|
+
|
|
1230
|
+
**新版本代码:**
|
|
1231
|
+
```javascript
|
|
1232
|
+
// 新版本只需要一个实例
|
|
1233
|
+
const sdk = new ZEEAvatarSDK(config);
|
|
1234
|
+
|
|
1235
|
+
// 统一初始化
|
|
1236
|
+
await sdk.initializeAvatar('avatar001', AvatarCameraType.WHOLE);
|
|
1237
|
+
```
|
|
1238
|
+
|
|
1239
|
+
### 完整迁移指南
|
|
1240
|
+
|
|
1241
|
+
```javascript
|
|
1242
|
+
// 旧版本完整代码
|
|
1243
|
+
class OldAvatarApp {
|
|
1244
|
+
async init() {
|
|
1245
|
+
// 1. 创建加载器
|
|
1246
|
+
this.loader = new ZEEAvatarLoader(config);
|
|
1247
|
+
|
|
1248
|
+
// 2. 初始化Unity
|
|
1249
|
+
this.avatarAPI = await this.loader.init();
|
|
1250
|
+
|
|
1251
|
+
// 3. 创建播报服务
|
|
1252
|
+
this.broadcastService = new BroadcastService({
|
|
1253
|
+
unityInstance: this.loader.getInstance(),
|
|
1254
|
+
callbacks: {
|
|
1255
|
+
onStart: () => console.log('播报开始'),
|
|
1256
|
+
onFinish: () => console.log('播报完成')
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
|
|
1260
|
+
// 4. 初始化数字人
|
|
1261
|
+
await this.avatarAPI.initializeAvatar('avatar001', 'whole');
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
async speak(text) {
|
|
1265
|
+
await this.broadcastService.startBroadcast({
|
|
1266
|
+
type: 'text',
|
|
1267
|
+
humanCode: 'avatar001',
|
|
1268
|
+
text: text,
|
|
1269
|
+
voiceCode: 'VOICE001',
|
|
1270
|
+
volume: 1.0,
|
|
1271
|
+
isSubtitle: false
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
destroy() {
|
|
1276
|
+
this.broadcastService?.destroy();
|
|
1277
|
+
this.loader?.destroy();
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
// 新版本对应代码
|
|
1282
|
+
class NewAvatarApp {
|
|
1283
|
+
async init() {
|
|
1284
|
+
// 1. 创建SDK实例
|
|
1285
|
+
this.sdk = new ZEEAvatarSDK(config);
|
|
1286
|
+
|
|
1287
|
+
// 2. 设置播报回调
|
|
1288
|
+
this.sdk.updateBroadcastCallbacks({
|
|
1289
|
+
onStart: () => console.log('播报开始'),
|
|
1290
|
+
onFinish: () => console.log('播报完成')
|
|
1291
|
+
});
|
|
1292
|
+
|
|
1293
|
+
// 3. 统一初始化(包含Unity初始化和数字人加载)
|
|
1294
|
+
await this.sdk.initializeAvatar('avatar001', AvatarCameraType.WHOLE);
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
async speak(text) {
|
|
1298
|
+
await this.sdk.startBroadcast({
|
|
1299
|
+
type: BroadcastType.TEXT,
|
|
1300
|
+
humanCode: 'avatar001',
|
|
1301
|
+
text: text,
|
|
1302
|
+
voiceCode: 'VOICE001',
|
|
1303
|
+
volume: 1.0,
|
|
1304
|
+
isSubtitle: false
|
|
1305
|
+
});
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
destroy() {
|
|
1309
|
+
this.sdk?.destroy();
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
```
|
|
1313
|
+
|
|
1314
|
+
## ❓ 常见问题
|
|
1315
|
+
|
|
1316
|
+
### Q1: Unity内容无法加载怎么办?
|
|
1317
|
+
|
|
1318
|
+
**A1:** 请按以下步骤排查:
|
|
1319
|
+
|
|
1320
|
+
1. **检查文件路径**:确保Unity构建文件路径配置正确
|
|
1321
|
+
2. **CORS问题**:如果文件在不同域名,需要配置CORS
|
|
1322
|
+
3. **网络连接**:确认网络可以访问构建文件URL
|
|
1323
|
+
4. **浏览器兼容性**:确认浏览器支持WebGL 2.0
|
|
1324
|
+
|
|
1325
|
+
```javascript
|
|
1326
|
+
// 检查资源可访问性
|
|
1327
|
+
async function checkResourcesAvailability(config) {
|
|
1328
|
+
const resources = [
|
|
1329
|
+
config.loaderUrl,
|
|
1330
|
+
config.dataUrl,
|
|
1331
|
+
config.frameworkUrl,
|
|
1332
|
+
config.codeUrl
|
|
1333
|
+
];
|
|
1334
|
+
|
|
1335
|
+
for (const url of resources) {
|
|
1336
|
+
try {
|
|
1337
|
+
const response = await fetch(url, { method: 'HEAD' });
|
|
1338
|
+
if (!response.ok) {
|
|
1339
|
+
console.error(`资源不可访问: ${url}`);
|
|
1340
|
+
}
|
|
1341
|
+
} catch (error) {
|
|
1342
|
+
console.error(`资源检查失败: ${url}`, error);
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
```
|
|
1347
|
+
|
|
1348
|
+
### Q2: 播报没有声音怎么办?
|
|
1349
|
+
|
|
1350
|
+
**A2:** 请检查以下几点:
|
|
1351
|
+
|
|
1352
|
+
1. **音量设置**:确认volume参数大于0
|
|
1353
|
+
2. **音频格式**:确认音频文件格式为MP3或WAV
|
|
1354
|
+
3. **音色编码**:确认voiceCode正确
|
|
1355
|
+
4. **浏览器策略**:现代浏览器需要用户交互才能播放音频
|
|
1356
|
+
|
|
1357
|
+
```javascript
|
|
1358
|
+
// 处理浏览器自动播放限制
|
|
1359
|
+
async function enableAudioPlayback() {
|
|
1360
|
+
try {
|
|
1361
|
+
// 创建一个静音的音频上下文
|
|
1362
|
+
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
|
1363
|
+
|
|
1364
|
+
// 用户交互后恢复音频上下文
|
|
1365
|
+
document.addEventListener('click', async () => {
|
|
1366
|
+
if (audioContext.state === 'suspended') {
|
|
1367
|
+
await audioContext.resume();
|
|
1368
|
+
}
|
|
1369
|
+
}, { once: true });
|
|
1370
|
+
} catch (error) {
|
|
1371
|
+
console.warn('音频上下文初始化失败:', error);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
```
|
|
1375
|
+
|
|
1376
|
+
### Q3: 如何处理多实例场景?
|
|
1377
|
+
|
|
1378
|
+
**A3:** 新版SDK原生支持多实例,每个实例都有独立的回调命名空间:
|
|
1379
|
+
|
|
1380
|
+
```javascript
|
|
1381
|
+
// 创建多个实例
|
|
1382
|
+
const instances = [];
|
|
1383
|
+
|
|
1384
|
+
for (let i = 0; i < 3; i++) {
|
|
1385
|
+
const sdk = new ZEEAvatarSDK({
|
|
1386
|
+
...config,
|
|
1387
|
+
containerId: `unity-container-${i}`
|
|
1388
|
+
});
|
|
1389
|
+
|
|
1390
|
+
instances.push(sdk);
|
|
1391
|
+
|
|
1392
|
+
// 每个实例独立初始化
|
|
1393
|
+
await sdk.initializeAvatar(`avatar00${i + 1}`);
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
// 独立控制每个实例
|
|
1397
|
+
instances[0].playMotion('wave_hand');
|
|
1398
|
+
instances[1].playMotion('bow');
|
|
1399
|
+
instances[2].startBroadcast({
|
|
1400
|
+
type: BroadcastType.TEXT,
|
|
1401
|
+
humanCode: 'avatar003',
|
|
1402
|
+
text: '我是第三个实例',
|
|
1403
|
+
voiceCode: 'VOICE001',
|
|
1404
|
+
volume: 1.0,
|
|
1405
|
+
isSubtitle: false
|
|
1406
|
+
});
|
|
1407
|
+
```
|
|
1408
|
+
|
|
1409
|
+
### Q4: 如何优化加载性能?
|
|
1410
|
+
|
|
1411
|
+
**A4:** 建议采用以下优化策略:
|
|
1412
|
+
|
|
1413
|
+
```javascript
|
|
1414
|
+
// 1. 资源预加载
|
|
1415
|
+
const preloadResources = async (config) => {
|
|
1416
|
+
const resources = [
|
|
1417
|
+
config.dataUrl,
|
|
1418
|
+
config.frameworkUrl,
|
|
1419
|
+
config.codeUrl
|
|
1420
|
+
];
|
|
1421
|
+
|
|
1422
|
+
// 并行预加载
|
|
1423
|
+
await Promise.all(
|
|
1424
|
+
resources.map(url =>
|
|
1425
|
+
fetch(url, { method: 'HEAD' })
|
|
1426
|
+
)
|
|
1427
|
+
);
|
|
1428
|
+
};
|
|
1429
|
+
|
|
1430
|
+
// 2. 懒加载策略
|
|
1431
|
+
class LazyAvatarManager {
|
|
1432
|
+
constructor(config) {
|
|
1433
|
+
this.config = config;
|
|
1434
|
+
this.sdk = null;
|
|
1435
|
+
this.loadPromise = null;
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
async load() {
|
|
1439
|
+
if (this.loadPromise) return this.loadPromise;
|
|
1440
|
+
|
|
1441
|
+
this.loadPromise = this.doLoad();
|
|
1442
|
+
return this.loadPromise;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
async doLoad() {
|
|
1446
|
+
if (this.sdk) return this.sdk;
|
|
1447
|
+
|
|
1448
|
+
this.sdk = new ZEEAvatarSDK(this.config);
|
|
1449
|
+
await this.sdk.initializeAvatar('avatar001');
|
|
1450
|
+
return this.sdk;
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
// 3. 缓存策略
|
|
1455
|
+
const avatarCache = new Map();
|
|
1456
|
+
|
|
1457
|
+
function getCachedSDK(key, config) {
|
|
1458
|
+
if (!avatarCache.has(key)) {
|
|
1459
|
+
avatarCache.set(key, new ZEEAvatarSDK(config));
|
|
1460
|
+
}
|
|
1461
|
+
return avatarCache.get(key);
|
|
1462
|
+
}
|
|
1463
|
+
```
|
|
1464
|
+
|
|
1465
|
+
### Q5: 如何处理内存泄漏?
|
|
1466
|
+
|
|
1467
|
+
**A5:** 务必正确管理SDK生命周期:
|
|
1468
|
+
|
|
1469
|
+
```javascript
|
|
1470
|
+
class AvatarManager {
|
|
1471
|
+
constructor() {
|
|
1472
|
+
this.sdk = null;
|
|
1473
|
+
this.isDestroyed = false;
|
|
1474
|
+
|
|
1475
|
+
// 监听页面卸载事件
|
|
1476
|
+
window.addEventListener('beforeunload', () => {
|
|
1477
|
+
this.destroy();
|
|
1478
|
+
});
|
|
1479
|
+
|
|
1480
|
+
// 监听页面可见性变化
|
|
1481
|
+
document.addEventListener('visibilitychange', () => {
|
|
1482
|
+
if (document.hidden) {
|
|
1483
|
+
this.pause();
|
|
1484
|
+
} else {
|
|
1485
|
+
this.resume();
|
|
1486
|
+
}
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
async init() {
|
|
1491
|
+
if (this.isDestroyed) return;
|
|
1492
|
+
|
|
1493
|
+
this.sdk = new ZEEAvatarSDK(config);
|
|
1494
|
+
await this.sdk.initializeAvatar('avatar001');
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
async pause() {
|
|
1498
|
+
if (this.sdk) {
|
|
1499
|
+
await this.sdk.unloadAvatar();
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
async resume() {
|
|
1504
|
+
if (this.sdk) {
|
|
1505
|
+
await this.sdk.initializeAvatar('avatar001');
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
destroy() {
|
|
1510
|
+
this.isDestroyed = true;
|
|
1511
|
+
|
|
1512
|
+
if (this.sdk) {
|
|
1513
|
+
this.sdk.destroy();
|
|
1514
|
+
this.sdk = null;
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
```
|
|
1519
|
+
|
|
1520
|
+
## 🆚 新旧版本对比
|
|
1521
|
+
|
|
1522
|
+
### 使用体验对比
|
|
1523
|
+
|
|
1524
|
+
| 对比项 | 旧版本 | 新版本 | 改进说明 |
|
|
1525
|
+
|:-------|:-------|:-------|:---------|
|
|
1526
|
+
| **类数量** | 3个类 | 1个类 | 简化使用 |
|
|
1527
|
+
| **初始化步骤** | 4步 | 1步 | 大幅简化 |
|
|
1528
|
+
| **多实例支持** | ❌ | ✅ | 新增功能 |
|
|
1529
|
+
| **回调冲突** | 有冲突 | 完全隔离 | 问题解决 |
|
|
1530
|
+
| **内部暴露** | 过度暴露 | 合理封装 | 更安全 |
|
|
1531
|
+
| **错误处理** | 分散处理 | 统一管理 | 更规范 |
|
|
1532
|
+
|
|
1533
|
+
### 代码量对比
|
|
1534
|
+
|
|
1535
|
+
**旧版本:**
|
|
1536
|
+
```javascript
|
|
1537
|
+
// 需要 15+ 行代码初始化
|
|
1538
|
+
const loader = new ZEEAvatarLoader(config);
|
|
1539
|
+
const avatarAPI = await loader.init();
|
|
1540
|
+
const broadcastService = new BroadcastService({
|
|
1541
|
+
unityInstance: loader.getInstance(),
|
|
1542
|
+
callbacks: { /* ... */ }
|
|
1543
|
+
});
|
|
1544
|
+
await avatarAPI.initializeAvatar('avatar001', 'whole');
|
|
1545
|
+
```
|
|
1546
|
+
|
|
1547
|
+
**新版本:**
|
|
1548
|
+
```javascript
|
|
1549
|
+
// 只需要 3 行代码
|
|
1550
|
+
const sdk = new ZEEAvatarSDK(config);
|
|
1551
|
+
await sdk.initializeAvatar('avatar001', AvatarCameraType.WHOLE);
|
|
1552
|
+
```
|
|
1553
|
+
|
|
1554
|
+
|
|
1555
|
+
**ZEE 3D Avatar SDK** - 让3D数字人集成变得简单而强大! 🚀
|
|
1556
|
+
|
|
1557
|
+
---
|
|
1558
|
+
|
|
1559
|
+
## 📖 旧版本文档
|
|
1560
|
+
|
|
1561
|
+
> **注意**:以下是旧版本SDK的使用说明,仅供未更新的用户参考。**强烈建议升级到新版本以获得更好的开发体验。**
|
|
1562
|
+
|
|
1563
|
+
<details>
|
|
1564
|
+
<summary>点击展开旧版本文档</summary>
|
|
1565
|
+
|
|
1566
|
+
### 旧版本使用方式
|
|
1567
|
+
|
|
1568
|
+
#### 1. 创建多个实例
|
|
1569
|
+
```javascript
|
|
1570
|
+
// 旧版本需要分别创建多个实例
|
|
1571
|
+
const loader = new ZEEAvatarLoader(config);
|
|
1572
|
+
const avatarAPI = await loader.init();
|
|
1573
|
+
const broadcastService = new BroadcastService({
|
|
1574
|
+
unityInstance: loader.getInstance(),
|
|
1575
|
+
callbacks: {
|
|
1576
|
+
onStart: () => console.log('播报开始'),
|
|
1577
|
+
onFinish: () => console.log('播报完成'),
|
|
1578
|
+
onError: (error) => console.error('播报错误:', error)
|
|
1579
|
+
}
|
|
1580
|
+
});
|
|
1581
|
+
```
|
|
1582
|
+
|
|
1583
|
+
#### 2. 分步初始化
|
|
1584
|
+
```javascript
|
|
1585
|
+
// 旧版本需要分步初始化
|
|
1586
|
+
await avatarAPI.initializeAvatar('avatar001', 'whole');
|
|
1587
|
+
```
|
|
1588
|
+
|
|
1589
|
+
#### 3. 手动管理生命周期
|
|
1590
|
+
```javascript
|
|
1591
|
+
// 旧版本需要手动管理各个实例
|
|
1592
|
+
broadcastService.destroy();
|
|
1593
|
+
loader.destroy();
|
|
1594
|
+
```
|
|
1595
|
+
|
|
1596
|
+
**⚠️ 旧版本问题**:
|
|
1597
|
+
- 多实例时回调函数冲突
|
|
1598
|
+
- 初始化流程复杂
|
|
1599
|
+
- 内部实例暴露过多
|
|
1600
|
+
- 错误处理不统一
|
|
1601
|
+
|
|
1602
|
+
**🚀 升级建议**:
|
|
1603
|
+
请尽快升级到新版本,享受更简单、更强大的SDK体验!
|
|
1604
|
+
|
|
1605
|
+
</details>
|
|
1606
|
+
|