@spatialwalk/avatarkit-rtc 1.0.0-beta.1 → 1.0.0-beta.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 +178 -113
- package/dist/core/AvatarPlayer.d.ts +59 -7
- package/dist/core/AvatarPlayer.d.ts.map +1 -1
- package/dist/index10.js +359 -36
- package/dist/index10.js.map +1 -1
- package/dist/index11.js +64 -346
- package/dist/index11.js.map +1 -1
- package/dist/index12.js +14 -104
- package/dist/index12.js.map +1 -1
- package/dist/index13.js +174 -14
- package/dist/index13.js.map +1 -1
- package/dist/index2.js +86 -18
- package/dist/index2.js.map +1 -1
- package/dist/index3.js +3 -3
- package/dist/index4.js +2 -2
- package/dist/index6.js +71 -6
- package/dist/index6.js.map +1 -1
- package/dist/index8.js +1 -1
- package/dist/index9.js +51 -162
- package/dist/index9.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Unified RTC adapter for avatarkit - supports LiveKit, Agora and other RTC providers.
|
|
4
4
|
|
|
5
|
+
📚 **Documentation**: [https://docs.spatialreal.ai/web-sdk/introduction](https://docs.spatialreal.ai/web-sdk/introduction)
|
|
6
|
+
|
|
7
|
+
> For server-side RTC SDK integration, please refer to the [online documentation](https://docs.spatialreal.ai/web-sdk/introduction).
|
|
8
|
+
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
7
11
|
```bash
|
|
@@ -10,7 +14,7 @@ pnpm add @spatialwalk/avatarkit-rtc
|
|
|
10
14
|
|
|
11
15
|
### Peer Dependencies
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
Install the RTC SDK based on your provider:
|
|
14
18
|
|
|
15
19
|
```bash
|
|
16
20
|
# LiveKit
|
|
@@ -22,36 +26,44 @@ pnpm add agora-rtc-sdk-ng
|
|
|
22
26
|
|
|
23
27
|
## Quick Start
|
|
24
28
|
|
|
29
|
+
When initializing `@spatialwalk/avatarkit`, use `DrivingServiceMode.host` since network communication is managed by this SDK.
|
|
30
|
+
|
|
25
31
|
```typescript
|
|
26
32
|
import { AvatarPlayer, LiveKitProvider, AgoraProvider } from '@spatialwalk/avatarkit-rtc';
|
|
27
|
-
import { AvatarView,
|
|
33
|
+
import { AvatarSDK, AvatarView, AvatarManager, DrivingServiceMode, Environment } from '@spatialwalk/avatarkit';
|
|
34
|
+
|
|
35
|
+
// 0. Initialize SDK (use host mode)
|
|
36
|
+
await AvatarSDK.initialize(appId, {
|
|
37
|
+
environment: Environment.cn, // or Environment.intl
|
|
38
|
+
drivingServiceMode: DrivingServiceMode.host,
|
|
39
|
+
});
|
|
28
40
|
|
|
29
|
-
// 1.
|
|
30
|
-
const avatar = await
|
|
41
|
+
// 1. Create Avatar and AvatarView
|
|
42
|
+
const avatar = await AvatarManager.shared.load(characterId);
|
|
31
43
|
const avatarView = new AvatarView(avatar, container);
|
|
32
44
|
|
|
33
|
-
// 2.
|
|
34
|
-
const provider = new LiveKitProvider(); //
|
|
45
|
+
// 2. Create Provider (choose LiveKit or Agora)
|
|
46
|
+
const provider = new LiveKitProvider(); // or new AgoraProvider()
|
|
35
47
|
|
|
36
|
-
// 3.
|
|
48
|
+
// 3. Create Player
|
|
37
49
|
const player = new AvatarPlayer(provider, avatarView, {
|
|
38
|
-
logLevel: 'warning', //
|
|
50
|
+
logLevel: 'warning', // optional
|
|
39
51
|
});
|
|
40
52
|
|
|
41
|
-
// 4.
|
|
53
|
+
// 4. Connect to RTC server
|
|
42
54
|
await player.connect({
|
|
43
55
|
url: 'wss://your-livekit-server.com',
|
|
44
56
|
token: 'your-token',
|
|
45
57
|
roomName: 'room-name',
|
|
46
58
|
});
|
|
47
59
|
|
|
48
|
-
// 5.
|
|
60
|
+
// 5. Start microphone
|
|
49
61
|
await player.startPublishing();
|
|
50
62
|
|
|
51
|
-
// 6.
|
|
63
|
+
// 6. Stop microphone
|
|
52
64
|
await player.stopPublishing();
|
|
53
65
|
|
|
54
|
-
// 7.
|
|
66
|
+
// 7. Disconnect
|
|
55
67
|
await player.disconnect();
|
|
56
68
|
```
|
|
57
69
|
|
|
@@ -59,7 +71,7 @@ await player.disconnect();
|
|
|
59
71
|
|
|
60
72
|
### AvatarPlayer
|
|
61
73
|
|
|
62
|
-
|
|
74
|
+
Main entry class that manages RTC connection and avatar rendering.
|
|
63
75
|
|
|
64
76
|
#### Constructor
|
|
65
77
|
|
|
@@ -67,69 +79,69 @@ await player.disconnect();
|
|
|
67
79
|
new AvatarPlayer(provider: RTCProvider, avatarView: AvatarView, options?: AvatarPlayerOptions)
|
|
68
80
|
```
|
|
69
81
|
|
|
70
|
-
|
|
82
|
+
**Parameters:**
|
|
71
83
|
|
|
72
|
-
|
|
|
73
|
-
|
|
74
|
-
| `provider` | `LiveKitProvider \| AgoraProvider` | RTC
|
|
75
|
-
| `avatarView` | `AvatarView` |
|
|
76
|
-
| `options` | `AvatarPlayerOptions` |
|
|
84
|
+
| Parameter | Type | Description |
|
|
85
|
+
|-----------|------|-------------|
|
|
86
|
+
| `provider` | `LiveKitProvider \| AgoraProvider` | RTC provider instance |
|
|
87
|
+
| `avatarView` | `AvatarView` | AvatarView instance from avatarkit |
|
|
88
|
+
| `options` | `AvatarPlayerOptions` | Optional configuration |
|
|
77
89
|
|
|
78
90
|
#### AvatarPlayerOptions
|
|
79
91
|
|
|
80
92
|
```typescript
|
|
81
93
|
interface AvatarPlayerOptions {
|
|
82
|
-
/**
|
|
94
|
+
/** Start speaking transition frames, default 5 (~200ms at 25fps) */
|
|
83
95
|
transitionStartFrameCount?: number;
|
|
84
96
|
|
|
85
|
-
/**
|
|
97
|
+
/** End speaking transition frames, default 40 (~1600ms at 25fps) */
|
|
86
98
|
transitionEndFrameCount?: number;
|
|
87
99
|
|
|
88
|
-
/**
|
|
100
|
+
/** Log level: 'info' | 'warning' | 'error' | 'none', default 'warning' */
|
|
89
101
|
logLevel?: LogLevel;
|
|
90
102
|
}
|
|
91
103
|
```
|
|
92
104
|
|
|
93
105
|
#### Properties
|
|
94
106
|
|
|
95
|
-
|
|
|
96
|
-
|
|
97
|
-
| `isConnected` | `boolean` |
|
|
107
|
+
| Property | Type | Description |
|
|
108
|
+
|----------|------|-------------|
|
|
109
|
+
| `isConnected` | `boolean` | Whether connected to RTC server |
|
|
98
110
|
|
|
99
111
|
#### Methods
|
|
100
112
|
|
|
101
113
|
##### connect(config)
|
|
102
114
|
|
|
103
|
-
|
|
115
|
+
Connect to RTC server.
|
|
104
116
|
|
|
105
117
|
```typescript
|
|
106
118
|
await player.connect(config: RTCConnectionConfig): Promise<void>
|
|
107
119
|
```
|
|
108
120
|
|
|
109
|
-
**LiveKit
|
|
121
|
+
**LiveKit Config:**
|
|
110
122
|
|
|
111
123
|
```typescript
|
|
112
124
|
interface LiveKitConnectionConfig {
|
|
113
|
-
url: string; // LiveKit
|
|
114
|
-
token: string; //
|
|
115
|
-
roomName: string; //
|
|
125
|
+
url: string; // LiveKit server URL (wss://...)
|
|
126
|
+
token: string; // Auth token
|
|
127
|
+
roomName: string; // Room name
|
|
116
128
|
}
|
|
117
129
|
```
|
|
118
130
|
|
|
119
|
-
**Agora
|
|
131
|
+
**Agora Config:**
|
|
120
132
|
|
|
121
133
|
```typescript
|
|
122
134
|
interface AgoraConnectionConfig {
|
|
123
135
|
appId: string; // Agora App ID
|
|
124
|
-
channel: string; //
|
|
125
|
-
token?: string; //
|
|
126
|
-
uid?: number; //
|
|
136
|
+
channel: string; // Channel name
|
|
137
|
+
token?: string; // Auth token (required in production)
|
|
138
|
+
uid?: number; // User ID (optional, 0 = auto assign)
|
|
127
139
|
}
|
|
128
140
|
```
|
|
129
141
|
|
|
130
142
|
##### disconnect()
|
|
131
143
|
|
|
132
|
-
|
|
144
|
+
Disconnect RTC connection and clean up all resources.
|
|
133
145
|
|
|
134
146
|
```typescript
|
|
135
147
|
await player.disconnect(): Promise<void>
|
|
@@ -137,7 +149,7 @@ await player.disconnect(): Promise<void>
|
|
|
137
149
|
|
|
138
150
|
##### startPublishing()
|
|
139
151
|
|
|
140
|
-
|
|
152
|
+
Start publishing microphone audio. Automatically requests microphone permission.
|
|
141
153
|
|
|
142
154
|
```typescript
|
|
143
155
|
await player.startPublishing(): Promise<void>
|
|
@@ -145,94 +157,135 @@ await player.startPublishing(): Promise<void>
|
|
|
145
157
|
|
|
146
158
|
##### stopPublishing()
|
|
147
159
|
|
|
148
|
-
|
|
160
|
+
Stop publishing microphone audio and release the device.
|
|
149
161
|
|
|
150
162
|
```typescript
|
|
151
163
|
await player.stopPublishing(): Promise<void>
|
|
152
164
|
```
|
|
153
165
|
|
|
166
|
+
##### publishAudio(track)
|
|
167
|
+
|
|
168
|
+
Publish custom audio track (advanced usage). For non-microphone audio sources like audio file playback.
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
await player.publishAudio(track: MediaStreamTrack): Promise<void>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Supported audio sources:**
|
|
175
|
+
|
|
176
|
+
| Source | How to obtain |
|
|
177
|
+
|--------|---------------|
|
|
178
|
+
| 🎤 Microphone | Use `startPublishing()` for convenience |
|
|
179
|
+
| 🎵 `<audio>` element | `audioElement.captureStream()` |
|
|
180
|
+
| 🖥️ Screen share audio | `getDisplayMedia({ audio: true })` |
|
|
181
|
+
| 🎹 Web Audio API | `audioContext.createMediaStreamDestination().stream` |
|
|
182
|
+
|
|
183
|
+
**Example:**
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
// Play audio from browser <audio> element
|
|
187
|
+
const audioEl = document.querySelector('audio');
|
|
188
|
+
const stream = audioEl.captureStream();
|
|
189
|
+
await player.publishAudio(stream.getAudioTracks()[0]);
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
##### unpublishAudio()
|
|
193
|
+
|
|
194
|
+
Stop publishing custom audio track.
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
await player.unpublishAudio(): Promise<void>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Note:** `unpublishAudio()` does not stop the track - caller is responsible for managing track lifecycle:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
await player.unpublishAudio();
|
|
204
|
+
stream.getTracks().forEach(t => t.stop()); // Clean up externally
|
|
205
|
+
```
|
|
206
|
+
|
|
154
207
|
##### getConnectionState()
|
|
155
208
|
|
|
156
|
-
|
|
209
|
+
Get current connection state.
|
|
157
210
|
|
|
158
211
|
```typescript
|
|
159
212
|
player.getConnectionState(): ConnectionState
|
|
160
213
|
```
|
|
161
214
|
|
|
162
|
-
**ConnectionState
|
|
215
|
+
**ConnectionState enum:**
|
|
163
216
|
|
|
164
|
-
|
|
|
165
|
-
|
|
166
|
-
| `'disconnected'` |
|
|
167
|
-
| `'connecting'` |
|
|
168
|
-
| `'connected'` |
|
|
169
|
-
| `'reconnecting'` |
|
|
170
|
-
| `'failed'` |
|
|
217
|
+
| Value | Description |
|
|
218
|
+
|-------|-------------|
|
|
219
|
+
| `'disconnected'` | Not connected |
|
|
220
|
+
| `'connecting'` | Connecting |
|
|
221
|
+
| `'connected'` | Connected |
|
|
222
|
+
| `'reconnecting'` | Reconnecting |
|
|
223
|
+
| `'failed'` | Connection failed |
|
|
171
224
|
|
|
172
225
|
##### getNativeClient()
|
|
173
226
|
|
|
174
|
-
|
|
227
|
+
Get underlying RTC client object for platform-specific features.
|
|
175
228
|
|
|
176
229
|
```typescript
|
|
177
230
|
player.getNativeClient(): unknown
|
|
178
231
|
```
|
|
179
232
|
|
|
180
|
-
|
|
233
|
+
**Return value:**
|
|
181
234
|
|
|
182
|
-
| Provider |
|
|
183
|
-
|
|
184
|
-
| LiveKit | `Room`
|
|
185
|
-
| Agora | `IAgoraRTCClient`
|
|
235
|
+
| Provider | Return type |
|
|
236
|
+
|----------|-------------|
|
|
237
|
+
| LiveKit | `Room` instance (exported as `LiveKitRoom`) |
|
|
238
|
+
| Agora | `IAgoraRTCClient` instance (exported as `AgoraClient`) |
|
|
186
239
|
|
|
187
|
-
|
|
240
|
+
**Type safety notes:**
|
|
188
241
|
|
|
189
|
-
-
|
|
190
|
-
-
|
|
242
|
+
- **Direct Provider usage**: Returns concrete type, no assertion needed
|
|
243
|
+
- **Via AvatarPlayer**: Returns `unknown`, requires manual type assertion
|
|
191
244
|
|
|
192
|
-
|
|
245
|
+
**Example:**
|
|
193
246
|
|
|
194
247
|
```typescript
|
|
195
|
-
//
|
|
248
|
+
// Method 1: Use Provider directly (recommended, full type hints)
|
|
196
249
|
import { LiveKitProvider, LiveKitRoom } from '@spatialwalk/avatarkit-rtc';
|
|
197
250
|
|
|
198
251
|
const provider = new LiveKitProvider();
|
|
199
|
-
const room = provider.getNativeClient(); //
|
|
200
|
-
console.log('
|
|
252
|
+
const room = provider.getNativeClient(); // Type: LiveKitRoom | null
|
|
253
|
+
console.log('Remote participants:', room?.remoteParticipants.size);
|
|
201
254
|
|
|
202
|
-
//
|
|
255
|
+
// Method 2: Via AvatarPlayer (requires assertion)
|
|
203
256
|
import { AvatarPlayer, LiveKitRoom } from '@spatialwalk/avatarkit-rtc';
|
|
204
257
|
|
|
205
258
|
const room = player.getNativeClient() as LiveKitRoom | null;
|
|
206
|
-
console.log('
|
|
259
|
+
console.log('Remote participants:', room?.remoteParticipants.size);
|
|
207
260
|
|
|
208
|
-
// Agora
|
|
261
|
+
// Agora example
|
|
209
262
|
import { AgoraProvider, AgoraClient } from '@spatialwalk/avatarkit-rtc';
|
|
210
263
|
|
|
211
264
|
const provider = new AgoraProvider();
|
|
212
|
-
const client = provider.getNativeClient(); //
|
|
213
|
-
console.log('
|
|
265
|
+
const client = provider.getNativeClient(); // Type: AgoraClient | null
|
|
266
|
+
console.log('Connection state:', client?.connectionState);
|
|
214
267
|
```
|
|
215
268
|
|
|
216
269
|
##### on(event, handler)
|
|
217
270
|
|
|
218
|
-
|
|
271
|
+
Listen to events.
|
|
219
272
|
|
|
220
273
|
```typescript
|
|
221
274
|
player.on(event: string, handler: Function): void
|
|
222
275
|
```
|
|
223
276
|
|
|
224
|
-
|
|
277
|
+
**Supported events:**
|
|
225
278
|
|
|
226
|
-
|
|
|
227
|
-
|
|
228
|
-
| `'connected'` | `()` |
|
|
229
|
-
| `'disconnected'` | `()` |
|
|
230
|
-
| `'error'` | `(error: Error)` |
|
|
231
|
-
| `'connection-state-changed'` | `(state: ConnectionState)` |
|
|
279
|
+
| Event | Callback params | Description |
|
|
280
|
+
|-------|-----------------|-------------|
|
|
281
|
+
| `'connected'` | `()` | Connection successful |
|
|
282
|
+
| `'disconnected'` | `()` | Disconnected |
|
|
283
|
+
| `'error'` | `(error: Error)` | Error occurred |
|
|
284
|
+
| `'connection-state-changed'` | `(state: ConnectionState)` | Connection state changed |
|
|
232
285
|
|
|
233
286
|
##### off(event, handler)
|
|
234
287
|
|
|
235
|
-
|
|
288
|
+
Remove event listener.
|
|
236
289
|
|
|
237
290
|
```typescript
|
|
238
291
|
player.off(event: string, handler: Function): void
|
|
@@ -242,7 +295,7 @@ player.off(event: string, handler: Function): void
|
|
|
242
295
|
|
|
243
296
|
### LiveKitProvider
|
|
244
297
|
|
|
245
|
-
LiveKit RTC
|
|
298
|
+
LiveKit RTC provider implementation.
|
|
246
299
|
|
|
247
300
|
```typescript
|
|
248
301
|
import { LiveKitProvider } from '@spatialwalk/avatarkit-rtc';
|
|
@@ -254,21 +307,21 @@ const provider = new LiveKitProvider();
|
|
|
254
307
|
|
|
255
308
|
### AgoraProvider
|
|
256
309
|
|
|
257
|
-
Agora RTC
|
|
310
|
+
Agora RTC provider implementation.
|
|
258
311
|
|
|
259
312
|
```typescript
|
|
260
313
|
import { AgoraProvider } from '@spatialwalk/avatarkit-rtc';
|
|
261
314
|
|
|
262
315
|
const provider = new AgoraProvider({
|
|
263
|
-
debugLogging: true, //
|
|
316
|
+
debugLogging: true, // optional: enable debug logs
|
|
264
317
|
});
|
|
265
318
|
```
|
|
266
319
|
|
|
267
|
-
**AgoraProviderOptions
|
|
320
|
+
**AgoraProviderOptions:**
|
|
268
321
|
|
|
269
322
|
```typescript
|
|
270
323
|
interface AgoraProviderOptions {
|
|
271
|
-
/**
|
|
324
|
+
/** Enable verbose debug logging, default false */
|
|
272
325
|
debugLogging?: boolean;
|
|
273
326
|
}
|
|
274
327
|
```
|
|
@@ -277,17 +330,17 @@ interface AgoraProviderOptions {
|
|
|
277
330
|
|
|
278
331
|
### Type Guards
|
|
279
332
|
|
|
280
|
-
|
|
333
|
+
Type guard functions for config type checking.
|
|
281
334
|
|
|
282
335
|
```typescript
|
|
283
336
|
import { isLiveKitConfig, isAgoraConfig } from '@spatialwalk/avatarkit-rtc';
|
|
284
337
|
|
|
285
338
|
if (isLiveKitConfig(config)) {
|
|
286
|
-
// config
|
|
339
|
+
// config is LiveKitConnectionConfig
|
|
287
340
|
}
|
|
288
341
|
|
|
289
342
|
if (isAgoraConfig(config)) {
|
|
290
|
-
// config
|
|
343
|
+
// config is AgoraConnectionConfig
|
|
291
344
|
}
|
|
292
345
|
```
|
|
293
346
|
|
|
@@ -295,31 +348,31 @@ if (isAgoraConfig(config)) {
|
|
|
295
348
|
|
|
296
349
|
### Native Client Types
|
|
297
350
|
|
|
298
|
-
SDK
|
|
351
|
+
SDK exports type aliases for underlying RTC clients, useful when using `getNativeClient()`:
|
|
299
352
|
|
|
300
353
|
```typescript
|
|
301
354
|
import type { LiveKitRoom, AgoraClient } from '@spatialwalk/avatarkit-rtc';
|
|
302
355
|
|
|
303
|
-
// LiveKitRoom = livekit-client
|
|
304
|
-
// AgoraClient = agora-rtc-sdk-ng
|
|
356
|
+
// LiveKitRoom = Room type from livekit-client
|
|
357
|
+
// AgoraClient = IAgoraRTCClient type from agora-rtc-sdk-ng
|
|
305
358
|
```
|
|
306
359
|
|
|
307
360
|
---
|
|
308
361
|
|
|
309
362
|
## Log Levels
|
|
310
363
|
|
|
311
|
-
SDK
|
|
364
|
+
SDK log level is configured via `AvatarPlayerOptions.logLevel`:
|
|
312
365
|
|
|
313
|
-
| Level |
|
|
314
|
-
|
|
315
|
-
| `'info'` |
|
|
316
|
-
| `'warning'` |
|
|
317
|
-
| `'error'` |
|
|
318
|
-
| `'none'` |
|
|
366
|
+
| Level | Output |
|
|
367
|
+
|-------|--------|
|
|
368
|
+
| `'info'` | All logs (connection state, frame processing, debug info) |
|
|
369
|
+
| `'warning'` | Warnings + errors (**default**) |
|
|
370
|
+
| `'error'` | Errors only |
|
|
371
|
+
| `'none'` | Disable all logs |
|
|
319
372
|
|
|
320
373
|
```typescript
|
|
321
374
|
const player = new AvatarPlayer(provider, avatarView, {
|
|
322
|
-
logLevel: 'info', //
|
|
375
|
+
logLevel: 'info', // Enable for debugging
|
|
323
376
|
});
|
|
324
377
|
```
|
|
325
378
|
|
|
@@ -327,19 +380,25 @@ const player = new AvatarPlayer(provider, avatarView, {
|
|
|
327
380
|
|
|
328
381
|
## Complete Example
|
|
329
382
|
|
|
330
|
-
### LiveKit
|
|
383
|
+
### LiveKit Integration
|
|
331
384
|
|
|
332
385
|
```typescript
|
|
333
386
|
import { AvatarPlayer, LiveKitProvider } from '@spatialwalk/avatarkit-rtc';
|
|
334
|
-
import { AvatarView,
|
|
387
|
+
import { AvatarSDK, AvatarView, AvatarManager, DrivingServiceMode, Environment } from '@spatialwalk/avatarkit';
|
|
335
388
|
|
|
336
389
|
async function initLiveKit() {
|
|
337
|
-
//
|
|
338
|
-
|
|
390
|
+
// Initialize SDK (use host mode)
|
|
391
|
+
await AvatarSDK.initialize('your-app-id', {
|
|
392
|
+
environment: Environment.cn,
|
|
393
|
+
drivingServiceMode: DrivingServiceMode.host,
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
// Create Avatar
|
|
397
|
+
const avatar = await AvatarManager.shared.load('character-id');
|
|
339
398
|
const container = document.getElementById('avatar-container')!;
|
|
340
399
|
const avatarView = new AvatarView(avatar, container);
|
|
341
400
|
|
|
342
|
-
//
|
|
401
|
+
// Create Player
|
|
343
402
|
const provider = new LiveKitProvider();
|
|
344
403
|
const player = new AvatarPlayer(provider, avatarView, {
|
|
345
404
|
logLevel: 'info',
|
|
@@ -347,54 +406,60 @@ async function initLiveKit() {
|
|
|
347
406
|
transitionEndFrameCount: 40,
|
|
348
407
|
});
|
|
349
408
|
|
|
350
|
-
//
|
|
409
|
+
// Listen to events
|
|
351
410
|
player.on('connected', () => console.log('Connected!'));
|
|
352
411
|
player.on('disconnected', () => console.log('Disconnected!'));
|
|
353
412
|
player.on('error', (err) => console.error('Error:', err));
|
|
354
413
|
|
|
355
|
-
//
|
|
414
|
+
// Connect
|
|
356
415
|
await player.connect({
|
|
357
416
|
url: 'wss://your-livekit-server.com',
|
|
358
417
|
token: 'your-token',
|
|
359
418
|
roomName: 'my-room',
|
|
360
419
|
});
|
|
361
420
|
|
|
362
|
-
//
|
|
421
|
+
// Start microphone
|
|
363
422
|
await player.startPublishing();
|
|
364
423
|
|
|
365
|
-
//
|
|
424
|
+
// Stop microphone
|
|
366
425
|
// await player.stopPublishing();
|
|
367
426
|
|
|
368
|
-
//
|
|
427
|
+
// Disconnect
|
|
369
428
|
// await player.disconnect();
|
|
370
429
|
}
|
|
371
430
|
```
|
|
372
431
|
|
|
373
|
-
### Agora
|
|
432
|
+
### Agora Integration
|
|
374
433
|
|
|
375
434
|
```typescript
|
|
376
435
|
import { AvatarPlayer, AgoraProvider } from '@spatialwalk/avatarkit-rtc';
|
|
377
|
-
import { AvatarView,
|
|
436
|
+
import { AvatarSDK, AvatarView, AvatarManager, DrivingServiceMode, Environment } from '@spatialwalk/avatarkit';
|
|
378
437
|
|
|
379
438
|
async function initAgora() {
|
|
380
|
-
//
|
|
381
|
-
|
|
439
|
+
// Initialize SDK (use host mode)
|
|
440
|
+
await AvatarSDK.initialize('your-app-id', {
|
|
441
|
+
environment: Environment.cn,
|
|
442
|
+
drivingServiceMode: DrivingServiceMode.host,
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
// Create Avatar
|
|
446
|
+
const avatar = await AvatarManager.shared.load('character-id');
|
|
382
447
|
const container = document.getElementById('avatar-container')!;
|
|
383
448
|
const avatarView = new AvatarView(avatar, container);
|
|
384
449
|
|
|
385
|
-
//
|
|
450
|
+
// Create Player
|
|
386
451
|
const provider = new AgoraProvider({ debugLogging: true });
|
|
387
452
|
const player = new AvatarPlayer(provider, avatarView);
|
|
388
453
|
|
|
389
|
-
//
|
|
454
|
+
// Connect
|
|
390
455
|
await player.connect({
|
|
391
456
|
appId: 'your-agora-app-id',
|
|
392
457
|
channel: 'my-channel',
|
|
393
|
-
token: 'your-token', //
|
|
394
|
-
uid: 0, // 0 =
|
|
458
|
+
token: 'your-token', // Required in production
|
|
459
|
+
uid: 0, // 0 = auto assign
|
|
395
460
|
});
|
|
396
461
|
|
|
397
|
-
//
|
|
462
|
+
// Start microphone
|
|
398
463
|
await player.startPublishing();
|
|
399
464
|
}
|
|
400
465
|
```
|
|
@@ -405,10 +470,10 @@ async function initAgora() {
|
|
|
405
470
|
|
|
406
471
|
| Feature | Chrome | Firefox | Safari | Edge |
|
|
407
472
|
|---------|--------|---------|--------|------|
|
|
408
|
-
| LiveKit (VP8 + RTCRtpScriptTransform) | ✅ 94+ | ✅ 117+ |
|
|
473
|
+
| LiveKit (VP8 + RTCRtpScriptTransform) | ✅ 94+ | ✅ 117+ | ✅ 15.4+ | ✅ 94+ |
|
|
409
474
|
| Agora (H.264 + SEI) | ✅ 74+ | ✅ 78+ | ✅ 14.1+ | ✅ 79+ |
|
|
410
475
|
|
|
411
|
-
|
|
476
|
+
**Note:** LiveKit requires browser support for `RTCRtpScriptTransform` API (Safari 15.4+ supported).
|
|
412
477
|
|
|
413
478
|
---
|
|
414
479
|
|
|
@@ -36,11 +36,20 @@ export interface AvatarPlayerOptions {
|
|
|
36
36
|
* const provider = new LiveKitProvider();
|
|
37
37
|
* const player = new AvatarPlayer(provider, avatarView);
|
|
38
38
|
*
|
|
39
|
-
* // Connect
|
|
39
|
+
* // Connect
|
|
40
40
|
* await player.connect({ url: 'wss://...', token: '...' });
|
|
41
|
-
* await player.startPublishing(); // Start microphone
|
|
42
41
|
*
|
|
43
|
-
* //
|
|
42
|
+
* // Option 1: Use microphone (most common)
|
|
43
|
+
* await player.startPublishing();
|
|
44
|
+
* await player.stopPublishing();
|
|
45
|
+
*
|
|
46
|
+
* // Option 2: Use custom audio source
|
|
47
|
+
* const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
48
|
+
* await player.publishAudio(stream.getAudioTracks()[0]);
|
|
49
|
+
* await player.unpublishAudio();
|
|
50
|
+
* stream.getTracks().forEach(t => t.stop());
|
|
51
|
+
*
|
|
52
|
+
* // Disconnect
|
|
44
53
|
* await player.disconnect();
|
|
45
54
|
* ```
|
|
46
55
|
*/
|
|
@@ -68,13 +77,56 @@ export declare class AvatarPlayer {
|
|
|
68
77
|
*/
|
|
69
78
|
disconnect(): Promise<void>;
|
|
70
79
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
80
|
+
* Publish an audio track to the RTC server.
|
|
81
|
+
*
|
|
82
|
+
* The audio source is controlled externally - you can pass any audio track:
|
|
83
|
+
* - Microphone: `getUserMedia({ audio: true })`
|
|
84
|
+
* - Browser audio: `audioElement.captureStream()`
|
|
85
|
+
* - Web Audio API: `audioContext.createMediaStreamDestination().stream`
|
|
86
|
+
* - Screen share audio: `getDisplayMedia({ audio: true })`
|
|
87
|
+
*
|
|
88
|
+
* @param track - MediaStreamTrack to publish (must be an audio track)
|
|
89
|
+
* @throws Error if not connected or track is invalid
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* // Microphone
|
|
94
|
+
* const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
95
|
+
* await player.publishAudio(stream.getAudioTracks()[0]);
|
|
96
|
+
*
|
|
97
|
+
* // Browser audio element
|
|
98
|
+
* const audioEl = document.querySelector('audio');
|
|
99
|
+
* const stream = audioEl.captureStream();
|
|
100
|
+
* await player.publishAudio(stream.getAudioTracks()[0]);
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
publishAudio(track: MediaStreamTrack): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Stop publishing audio.
|
|
106
|
+
* Note: This does NOT stop the track - the caller is responsible for managing the track lifecycle.
|
|
107
|
+
*/
|
|
108
|
+
unpublishAudio(): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* Start publishing microphone audio.
|
|
111
|
+
*
|
|
112
|
+
* This requests microphone permission and publishes it to the RTC session.
|
|
113
|
+
* For custom audio sources (e.g., audio files), use `publishAudio(track)` instead.
|
|
114
|
+
*
|
|
115
|
+
* @throws Error if not connected, permission denied, or no microphone found
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```typescript
|
|
119
|
+
* await player.startPublishing();
|
|
120
|
+
* // ... later
|
|
121
|
+
* await player.stopPublishing();
|
|
122
|
+
* ```
|
|
74
123
|
*/
|
|
75
124
|
startPublishing(): Promise<void>;
|
|
76
125
|
/**
|
|
77
|
-
* Stop publishing microphone audio.
|
|
126
|
+
* Stop publishing microphone audio and release the microphone.
|
|
127
|
+
*
|
|
128
|
+
* This stops the microphone track and releases the device.
|
|
129
|
+
* If you used `publishAudio()` with a custom track, use `unpublishAudio()` instead.
|
|
78
130
|
*/
|
|
79
131
|
stopPublishing(): Promise<void>;
|
|
80
132
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AvatarPlayer.d.ts","sourceRoot":"","sources":["../../src/core/AvatarPlayer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEpD,OAAO,KAAK,EAA2B,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,
|
|
1
|
+
{"version":3,"file":"AvatarPlayer.d.ts","sourceRoot":"","sources":["../../src/core/AvatarPlayer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEpD,OAAO,KAAK,EAA2B,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAA2B,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAGlE,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,wBAAwB,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,qBAAa,YAAY;IAmBvB;;;;;OAKG;gBAED,QAAQ,EAAE,WAAW,EACrB,UAAU,EAAE,UAAU,EACtB,OAAO,CAAC,EAAE,mBAAmB;IAmB/B;;OAEG;IACH,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAWzD;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAkBjC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACG,YAAY,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB1D;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IASrC;;;;;;;;;;;;;;OAcG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBtC;;;;;OAKG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAYrC;;;OAGG;IACH,kBAAkB,IAAI,MAAM;IAI5B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,eAAe,IAAI,OAAO;IAI1B;;;;OAIG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAClC,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC5B,IAAI;IAIP;;;;OAIG;IACH,GAAG,CAAC,CAAC,SAAS,MAAM,iBAAiB,EACnC,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC5B,IAAI;CAqGR"}
|