@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 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
- 根据使用的 RTC 提供商安装对应的 SDK:
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, Avatar } from '@spatialwalk/avatarkit';
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. 创建 Avatar AvatarView(来自 avatarkit)
30
- const avatar = await Avatar.create(characterId);
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. 创建 Provider(选择 LiveKit Agora
34
- const provider = new LiveKitProvider(); // new AgoraProvider()
45
+ // 2. Create Provider (choose LiveKit or Agora)
46
+ const provider = new LiveKitProvider(); // or new AgoraProvider()
35
47
 
36
- // 3. 创建 Player
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. 连接到 RTC 服务器
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
- 主入口类,统一管理 RTC 连接和 Avatar 渲染。
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` | avatarkit 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
- /** 开始说话过渡帧数,默认 5 (~200ms at 25fps) */
94
+ /** Start speaking transition frames, default 5 (~200ms at 25fps) */
83
95
  transitionStartFrameCount?: number;
84
96
 
85
- /** 结束说话过渡帧数,默认 40 (~1600ms at 25fps) */
97
+ /** End speaking transition frames, default 40 (~1600ms at 25fps) */
86
98
  transitionEndFrameCount?: number;
87
99
 
88
- /** 日志级别:'info' | 'warning' | 'error' | 'none',默认 'warning' */
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` | 是否已连接到 RTC 服务器 |
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
- 连接到 RTC 服务器。
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 服务器 URL (wss://...)
114
- token: string; // 认证 Token
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; // 认证 Token(生产环境必需)
126
- uid?: number; // 用户 ID(可选,0 = 自动分配)
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
- 断开 RTC 连接,清理所有资源。
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
- 获取底层 RTC 客户端对象,用于访问平台特定功能。
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` 实例(SDK 导出为 `LiveKitRoom`) |
185
- | Agora | `IAgoraRTCClient` 实例(SDK 导出为 `AgoraClient`) |
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
- - **直接使用 Provider**:返回具体类型,无需断言
190
- - **通过 AvatarPlayer 使用**:返回 `unknown`,需要手动类型断言
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
- // 方式 1:直接使用 Provider(推荐,有完整类型提示)
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(); // 类型: LiveKitRoom | null
200
- console.log('远程参与者数量:', room?.remoteParticipants.size);
252
+ const room = provider.getNativeClient(); // Type: LiveKitRoom | null
253
+ console.log('Remote participants:', room?.remoteParticipants.size);
201
254
 
202
- // 方式 2:通过 AvatarPlayer 使用(需手动断言)
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('远程参与者数量:', room?.remoteParticipants.size);
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(); // 类型: AgoraClient | null
213
- console.log('连接状态:', client?.connectionState);
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
- /** 启用详细调试日志,默认 false */
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 LiveKitConnectionConfig
339
+ // config is LiveKitConnectionConfig
287
340
  }
288
341
 
289
342
  if (isAgoraConfig(config)) {
290
- // config AgoraConnectionConfig
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 导出了底层 RTC 客户端的类型别名,方便在使用 `getNativeClient()` 时获得类型支持:
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 的 Room 类型
304
- // AgoraClient = agora-rtc-sdk-ng 的 IAgoraRTCClient 类型
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 日志级别通过 `AvatarPlayerOptions.logLevel` 配置:
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, Avatar } from '@spatialwalk/avatarkit';
387
+ import { AvatarSDK, AvatarView, AvatarManager, DrivingServiceMode, Environment } from '@spatialwalk/avatarkit';
335
388
 
336
389
  async function initLiveKit() {
337
- // 初始化 Avatar
338
- const avatar = await Avatar.create('character-id');
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
- // 创建 Player
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, Avatar } from '@spatialwalk/avatarkit';
436
+ import { AvatarSDK, AvatarView, AvatarManager, DrivingServiceMode, Environment } from '@spatialwalk/avatarkit';
378
437
 
379
438
  async function initAgora() {
380
- // 初始化 Avatar
381
- const avatar = await Avatar.create('character-id');
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
- // 创建 Player
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+ | | ✅ 94+ |
473
+ | LiveKit (VP8 + RTCRtpScriptTransform) | ✅ 94+ | ✅ 117+ | 15.4+ | ✅ 94+ |
409
474
  | Agora (H.264 + SEI) | ✅ 74+ | ✅ 78+ | ✅ 14.1+ | ✅ 79+ |
410
475
 
411
- **注意:** LiveKit 需要浏览器支持 `RTCRtpScriptTransform` API
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 and start
39
+ * // Connect
40
40
  * await player.connect({ url: 'wss://...', token: '...' });
41
- * await player.startPublishing(); // Start microphone
42
41
  *
43
- * // Disconnect when done
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
- * Start publishing microphone audio to the RTC server.
72
- * Requests microphone permission and starts publishing.
73
- * @throws Error if permission denied or no microphone found
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,EAAmB,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAG1D,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,wBAAwB,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;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;IAejC;;;;OAIG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAYtC;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBrC;;;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;CA+FR"}
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"}