@vivix-ai/ivi-frontend-sdk 0.2.3 → 0.3.1

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,32 +2,32 @@
2
2
 
3
3
  用于前端应用集成 IVI 实时能力的 TypeScript SDK,包含:
4
4
 
5
- - 基于 `@vivix/ivi-sdk-ts` 的 runtime 协调层
5
+ - 基于 `@vivix-ai/ivi-sdk-ts` 的 runtime 协调层
6
6
  - 面向舞台渲染的 React 组件与 hooks
7
7
 
8
8
  ## 安装依赖
9
9
 
10
- 当前包尚未发布到 npm,通过 **GitLab 仓库地址**直接安装:
10
+ 当前包发布到 npm 官方仓库,包名为 `@vivix-ai/ivi-frontend-sdk`。
11
+
12
+ 安装 SDK:
11
13
 
12
14
  ```bash
13
15
  # npm
14
- npm install git+https://gitlab.vivix.work/vinf-2.0/ivi-sdk/ivi-frontend-sdk.git#main
16
+ npm install @vivix-ai/ivi-frontend-sdk
15
17
 
16
18
  # pnpm
17
- pnpm add git+https://gitlab.vivix.work/vinf-2.0/ivi-sdk/ivi-frontend-sdk.git#main
19
+ pnpm add @vivix-ai/ivi-frontend-sdk
18
20
 
19
21
  # yarn
20
- yarn add git+https://gitlab.vivix.work/vinf-2.0/ivi-sdk/ivi-frontend-sdk.git#main
22
+ yarn add @vivix-ai/ivi-frontend-sdk
21
23
  ```
22
24
 
23
- > **推荐使用 `#main` 分支。** `dev` 分支可能引入尚未稳定的新特性,不保证向后兼容;`main` 分支仅包含经过验证的变更。如需锁定到更精确的版本,可替换为具体 tag 或 commit hash。
24
-
25
25
  安装后 `package.json` 中会出现类似条目:
26
26
 
27
27
  ```json
28
28
  {
29
29
  "dependencies": {
30
- "@vivix/ivi-frontend-sdk": "git+https://gitlab.vivix.work/vinf-2.0/ivi-sdk/ivi-frontend-sdk.git#main"
30
+ "@vivix-ai/ivi-frontend-sdk": "^0.3.0"
31
31
  }
32
32
  }
33
33
  ```
@@ -35,22 +35,16 @@ yarn add git+https://gitlab.vivix.work/vinf-2.0/ivi-sdk/ivi-frontend-sdk.git#mai
35
35
  **更新到最新版本**:
36
36
 
37
37
  ```bash
38
- # npm(Git 依赖建议显式指定分支、tag 或 commit)
39
- npm install git+https://gitlab.vivix.work/vinf-2.0/ivi-sdk/ivi-frontend-sdk.git#main
38
+ # npm
39
+ npm update @vivix-ai/ivi-frontend-sdk
40
40
 
41
41
  # pnpm
42
- pnpm add git+https://gitlab.vivix.work/vinf-2.0/ivi-sdk/ivi-frontend-sdk.git#main
42
+ pnpm update @vivix-ai/ivi-frontend-sdk
43
43
 
44
- # 若 lockfile 固定了旧 commit,可重新安装或删除 lock 中该依赖条目后 install
45
- npm install
44
+ # yarn
45
+ yarn up @vivix-ai/ivi-frontend-sdk
46
46
  ```
47
47
 
48
- ### `dist` 与 Git 直装
49
-
50
- `package.json` 的 `main` / `module` / `types` / `exports` 均指向 `dist/`,且 npm 包通过 `"files": ["dist"]` 发布。从 **Git 引用安装**(如 `git+https://…#dev`)时,npm 只会打包 `files` 所列内容;因此 **`dist/` 已纳入版本库**,克隆默认分支即可得到可运行、可解析类型的产物。
51
-
52
- **协作约定**:修改 `src/` 后必须在本地执行 `npm run build`(或 `pnpm run build`),并将**与本次源码变更对应的一次完整 `dist/` 输出**一并提交:可与功能改动放在**同一提交**,或在必要时单独提交,提交信息示例:`chore: 重新构建 dist`。禁止只改源码而不更新 `dist/`,避免仓库内源码与产物不一致。
53
-
54
48
  ### Peer Dependencies
55
49
 
56
50
  React 为可选 peer dependency,仅使用 React 组件时需要:
@@ -64,34 +58,6 @@ React 为可选 peer dependency,仅使用 React 组件时需要:
64
58
 
65
59
  如果只使用 runtime 能力、不接入 React 组件与 hooks,可忽略本文中的 React 用法部分。
66
60
 
67
- ## 包导出与导入方式
68
-
69
- 当前仅支持单一主入口:
70
-
71
- | 入口 | 路径 | 说明 |
72
- |------|------|------|
73
- | 主入口 | `@vivix/ivi-frontend-sdk` | 导出 runtime 能力、`IviFrontendSdk`、以及当前公开的 React API:`IVIStageView`、`IVITrackSlot`、`useManagedIviRuntime`、`useIviStageView` |
74
-
75
- **导入示例**:
76
-
77
- ```ts
78
- // 底层 client 由 @vivix/ivi-sdk-ts 提供
79
- import { IviClient } from "@vivix/ivi-sdk-ts";
80
-
81
- // 本包主入口
82
- import {
83
- IviRuntimeCoordinator,
84
- IviRuntimeDispatcher,
85
- IviFrontendSdk,
86
- IVIStageView,
87
- IVITrackSlot,
88
- useManagedIviRuntime,
89
- useIviStageView
90
- } from "@vivix/ivi-frontend-sdk";
91
- ```
92
-
93
- > 当前包没有 `@vivix/ivi-frontend-sdk/core` / `@vivix/ivi-frontend-sdk/react` 子入口;底层 WebSocket client、事件解析与协议类型请直接从 `@vivix/ivi-sdk-ts` 导入。
94
-
95
61
  ---
96
62
 
97
63
  ## 快速开始
@@ -99,12 +65,15 @@ import {
99
65
  ### 1)创建 client + runtime
100
66
 
101
67
  ```ts
102
- import { IviClient } from "@vivix/ivi-sdk-ts";
103
- import { IviRuntimeCoordinator } from "@vivix/ivi-frontend-sdk";
68
+ import { IviClient } from "@vivix-ai/ivi-sdk-ts";
69
+ import { IviRuntimeCoordinator } from "@vivix-ai/ivi-frontend-sdk";
70
+ import { LiveKitBrowserTransport } from "@vivix-ai/ivi-sdk-ts/transports/livekit-browser";
104
71
 
105
72
  const client = new IviClient({
106
- url: "wss://your-domain/v1/realtime",
107
- sessionId: "sess_xxx",
73
+ transport: new LiveKitBrowserTransport({
74
+ url: "wss://livekit.example.com",
75
+ token: "livekit_access_token"
76
+ }),
108
77
  onParseError: (error, raw) => {
109
78
  console.error("parse error", error, raw);
110
79
  }
@@ -120,17 +89,42 @@ const runtime = new IviRuntimeCoordinator(client, {
120
89
  await runtime.start();
121
90
  ```
122
91
 
92
+ 也可以使用 `IviFrontendSdk` 创建 client/runtime:
93
+
94
+ ```ts
95
+ import { IviFrontendSdk } from "@vivix-ai/ivi-frontend-sdk";
96
+ import { LiveKitBrowserTransport } from "@vivix-ai/ivi-sdk-ts/transports/livekit-browser";
97
+
98
+ const sdk = new IviFrontendSdk();
99
+ const runtime = sdk.createRuntimeCoordinator(
100
+ {
101
+ transport: new LiveKitBrowserTransport({
102
+ url: "wss://livekit.example.com",
103
+ token: "livekit_access_token"
104
+ })
105
+ },
106
+ {
107
+ syncStageOnSessionCreated: true
108
+ }
109
+ );
110
+
111
+ await runtime.start();
112
+ ```
113
+
123
114
  **使用自定义 WebSocket 运行时**(Node.js / 自定义环境):
124
115
 
125
116
  ```ts
126
117
  import WebSocket from "ws"; // Node.js 环境
127
- import { IviClient } from "@vivix/ivi-sdk-ts";
128
- import { IviRuntimeCoordinator } from "@vivix/ivi-frontend-sdk";
118
+ import { IviClient } from "@vivix-ai/ivi-sdk-ts";
119
+ import { WebSocketTransport } from "@vivix-ai/ivi-sdk-ts/transports/websocket";
120
+ import { IviRuntimeCoordinator } from "@vivix-ai/ivi-frontend-sdk";
129
121
 
130
122
  const client = new IviClient({
131
- url: "wss://your-domain/v1/realtime",
132
- sessionId: "sess_xxx",
133
- socketFactory: (url, protocols) => new WebSocket(url, protocols),
123
+ transport: new WebSocketTransport({
124
+ url: "wss://your-domain/v1/realtime",
125
+ sessionId: "sess_xxx",
126
+ socketFactory: (url, protocols) => new WebSocket(url, protocols)
127
+ }),
134
128
  onParseError: (error, raw) => {
135
129
  console.error("parse error", error, raw);
136
130
  }
@@ -140,15 +134,13 @@ const runtime = new IviRuntimeCoordinator(client);
140
134
  await runtime.start();
141
135
  ```
142
136
 
143
- `IviClientConfig` 关键配置:
137
+ `IviFrontendClientConfig` 等同于 `@vivix-ai/ivi-sdk-ts` 的 `IviClientConfig`,需要直接传入通用 `transport`。
144
138
 
145
139
  | 参数 | 类型 | 说明 |
146
140
  |------|------|------|
147
- | `protocols` | `string \| string[]` | WebSocket 子协议 |
148
- | `sessionId` | `string` | 会话 ID,连接时自动追加到 URL query `session_id=<id>` |
149
- | `socketFactory` | `(url, protocols?) => WebSocket` | 自定义 Socket 工厂,用于替换默认 WebSocket 构造 |
141
+ | `transport` | `IviRealtimeTransport` | 通用 transport,直接透传给 `@vivix-ai/ivi-sdk-ts`;浏览器 LiveKit 场景可传 `LiveKitBrowserTransport` |
150
142
  | `onParseError` | `(error, rawMessage) => void` | 事件解析失败回调 |
151
- | `onLog` | `(entry) => void` | `IviClient` 链路日志回调,包含发送、WebSocket 状态和重连链路 |
143
+ | `onLog` | `(entry) => void` | `IviClient` 链路日志回调,包含发送、transport 状态和重连链路 |
152
144
  | `reconnect` | `IviClientReconnectOptions` | 自动重连配置;默认启用,指数退避 |
153
145
  | `sendWaitTimeoutMs` | `number` | 发送时等待连接恢复的超时,默认 `30000` ms,`<=0` 表示无限等待 |
154
146
 
@@ -172,14 +164,14 @@ runtime.stop();
172
164
  ### 3)发送用户文本并触发模型回复
173
165
 
174
166
  ```ts
175
- const result = await runtime.sendUserTextAndTriggerStreamResponse({
167
+ const result = await runtime.sendUserTextAndTriggerResponse({
176
168
  streamId: "stream_001",
177
169
  text: "你好",
178
170
  callbacks: {
179
171
  onConversationItemAdded: (event) => console.log("item added"),
180
172
  onConversationItemDone: (event) => console.log("item done"),
181
173
  onConversationItemReady: ({ itemId }) => console.log("item ready:", itemId),
182
- onStreamResponseCreated: (event) => console.log("response created")
174
+ onResponseCreated: (event) => console.log("response created")
183
175
  }
184
176
  });
185
177
  console.log("完成:", result.itemId, result.streamId);
@@ -198,8 +190,8 @@ runtime.sendSessionSourcePlaybackCompleted("source_001", "track_001");
198
190
  | 字段 | 类型 | 说明 |
199
191
  |------|------|------|
200
192
  | `status` | `"idle" \| "connecting" \| "syncing" \| "running" \| "stopped"` | 生命周期状态 |
201
- | `session` | `IviRealtimeSession \| null` | 当前会话 |
202
- | `stage` | `IviStage \| null` | 当前 stage(slot → track 映射) |
193
+ | `session` | `IviRealtimeSessionConfig \| null` | 当前会话(来自 `@vivix-ai/ivi-sdk-ts`) |
194
+ | `stage` | `IviStageComposition \| null` | 当前 stage(slot → track 映射,来自 `@vivix-ai/ivi-sdk-ts`) |
203
195
  | `tracks` | `Map<string, IviTrack>` | 所有 track |
204
196
  | `sources` | `Map<string, IviRuntimeSource>` | 所有 source(含 `status: created \| ready \| failed`) |
205
197
  | `conversationItems` | `Map<string, IviRuntimeConversationItem>` | 对话条目映射 |
@@ -212,11 +204,17 @@ runtime.sendSessionSourcePlaybackCompleted("source_001", "track_001");
212
204
  ### 方式 A:传入外部 runtime
213
205
 
214
206
  ```tsx
215
- import { IviClient } from "@vivix/ivi-sdk-ts";
216
- import { IviRuntimeCoordinator, IVIStageView, IVITrackSlot, useIviStageView } from "@vivix/ivi-frontend-sdk";
207
+ import { IviClient } from "@vivix-ai/ivi-sdk-ts";
208
+ import { IviRuntimeCoordinator, IVIStageView, IVITrackSlot, useIviStageView } from "@vivix-ai/ivi-frontend-sdk";
209
+ import { LiveKitBrowserTransport } from "@vivix-ai/ivi-sdk-ts/transports/livekit-browser";
217
210
 
218
211
  // 初始化 runtime(参考上方 Core 用法)
219
- const client = new IviClient({ url: "wss://your-domain/v1/realtime", sessionId: "sess_xxx" });
212
+ const client = new IviClient({
213
+ transport: new LiveKitBrowserTransport({
214
+ url: "wss://livekit.example.com",
215
+ token: "livekit_access_token"
216
+ })
217
+ });
220
218
  const runtime = new IviRuntimeCoordinator(client);
221
219
  await runtime.start();
222
220
 
@@ -244,16 +242,19 @@ export function StagePage() {
244
242
  ### 方式 B:使用 `useManagedIviRuntime` 管理 runtime
245
243
 
246
244
  ```tsx
247
- import { IVIStageView, IVITrackSlot, useManagedIviRuntime } from "@vivix/ivi-frontend-sdk";
245
+ import { IVIStageView, IVITrackSlot, useManagedIviRuntime } from "@vivix-ai/ivi-frontend-sdk";
246
+ import { LiveKitBrowserTransport } from "@vivix-ai/ivi-sdk-ts/transports/livekit-browser";
248
247
 
249
- export function AutoStagePage({ sessionId }: { sessionId: string }) {
248
+ export function AutoStagePage({ livekitToken }: { livekitToken: string }) {
250
249
  const runtime = useManagedIviRuntime({
251
250
  clientConfig: {
252
- url: "https://your-domain.com/v1/realtime",
253
- sessionId
251
+ transport: new LiveKitBrowserTransport({
252
+ url: "wss://livekit.example.com",
253
+ token: livekitToken
254
+ })
254
255
  },
255
256
  onLog: (entry) => {
256
- // 统一收集 client / runtime / TRTC 的 IVI 链路日志
257
+ // 统一收集 client / runtime / TRTC / LiveKit 的 IVI 链路日志
257
258
  console.log(entry.tag, entry.message, entry.data);
258
259
  },
259
260
  onRuntimeInitError: (err) => console.error("runtime init failed", err)
@@ -267,14 +268,12 @@ export function AutoStagePage({ sessionId }: { sessionId: string }) {
267
268
  }
268
269
  ```
269
270
 
270
- `useManagedIviRuntime` 的地址规则:
271
-
272
- 1. 使用 `clientConfig.url`
273
- 2. 若 `clientConfig.url` 为 `https://` / `http://`,内部会自动确保为 `wss://` / `ws://`
274
- 3. 若 `clientConfig.sessionId` 为空,则不创建 runtime
275
- 4. 若 `clientConfig.url` 为空,会通过 `onRuntimeInitError` 抛出初始化错误;若未提供回调,则直接抛错
271
+ `useManagedIviRuntime` 的连接规则:
276
272
 
277
- 连接时自动追加 query:`?session_id=<sessionId>`。
273
+ 1. 使用 `clientConfig.transport`
274
+ 2. 若 `clientConfig.transport` 为空,则不创建 runtime
275
+ 3. 浏览器 LiveKit 场景可传 `LiveKitBrowserTransport`
276
+ 4. WebSocket、测试 fake transport 或其它 transport 也通过同一个 `transport` 字段传入
278
277
 
279
278
  ---
280
279
 
@@ -292,17 +291,17 @@ function useManagedIviRuntime(config: IviManagedRuntimeConfig): IviRuntimeCoordi
292
291
  - `autoStart` 为 `true` 时自动调用 `runtime.start()`
293
292
  - 卸载时自动 `runtime.stop()`
294
293
  - 初始化错误通过 `onRuntimeInitError` 上抛
295
- - 通过 `onLog` 统一收集 `IviClient`、runtime 状态变更、TRTC 管理器等 IVI 链路日志
294
+ - 通过 `onLog` 统一收集 `IviClient`、runtime 状态变更、TRTC / LiveKit 管理器等 IVI 链路日志
296
295
 
297
296
  `IviManagedRuntimeConfig` 关键字段:
298
297
 
299
298
  | 字段 | 类型 | 默认值 | 说明 |
300
299
  |------|------|--------|------|
301
- | `clientConfig` | `IviClientConfig` | — | `IviClient` 配置;其中 `url` 用于建立连接,`sessionId` 用于决定是否创建 runtime |
300
+ | `clientConfig` | `Partial<IviFrontendClientConfig>` | — | `IviClient` 配置;`transport` 为空时不创建 runtime |
302
301
  | `autoStart` | `boolean` | `true` | 是否自动启动 runtime |
303
302
  | `runtimeConfig` | `IviRuntimeCoordinatorConfig` | — | 透传给 `IviRuntimeCoordinator` |
304
303
  | `onRuntimeInitError` | `(error) => void` | — | 初始化或启动失败回调 |
305
- | `onLog` | `(entry) => void` | — | 统一日志回调,覆盖 `[IVI-SEND]`、`[IVI-WS]`、`[IVI-RECONNECT]`、`[IVI-EVT]`、`[IVI-STATE]`、`[IVI-TRTC]` |
304
+ | `onLog` | `(entry) => void` | — | 统一日志回调,覆盖 `[IVI-SEND]`、`[IVI-TRANSPORT]`、`[IVI-RECONNECT]`、`[IVI-EVT]`、`[IVI-STATE]`、`[IVI-TRTC]`、`[IVI-LIVEKIT]` |
306
305
 
307
306
  `onLog` 的统一入参格式:
308
307
 
@@ -310,7 +309,7 @@ function useManagedIviRuntime(config: IviManagedRuntimeConfig): IviRuntimeCoordi
310
309
  interface IviManagedRuntimeLogEntry {
311
310
  level: "info" | "warn" | "error";
312
311
  source: "client" | "runtime";
313
- tag: string; // 例如 "[IVI-WS]"、"[IVI-STATE]"
312
+ tag: string; // 例如 "[IVI-TRANSPORT]"、"[IVI-STATE]"
314
313
  message: string; // 带 tag 的可读日志
315
314
  args: unknown[]; // 接近原 console 调用的参数
316
315
  data?: unknown; // 结构化数据
@@ -341,7 +340,50 @@ function MyOverlay() {
341
340
  }
342
341
  ```
343
342
 
344
- 以下 hooks 为 `IVITrackSlot` 内部实现,当前不属于公开导出 API。
343
+ ### `useRuntimeState`
344
+
345
+ ```ts
346
+ function useRuntimeState(runtime: IviRuntimeCoordinator | null): IviRuntimeState;
347
+ ```
348
+
349
+ 订阅 runtime 状态变化。`runtime` 为 `null` 时返回 `EMPTY_RUNTIME_STATE`。
350
+
351
+ ### `useIviSubtitles`
352
+
353
+ ```ts
354
+ function useIviSubtitles(
355
+ runtime: IviRuntimeCoordinator | null,
356
+ options?: IviUseSubtitlesOptions
357
+ ): IviSubtitleItem[];
358
+ ```
359
+
360
+ 基于 runtime 的 conversation / response 事件维护字幕队列,不负责渲染,也不按时间自动消失。
361
+
362
+ | Option | 类型 | 默认值 | 说明 |
363
+ |--------|------|--------|------|
364
+ | `roles` | `IviSubtitleRole \| IviSubtitleRole[]` | `"user"` | 要收集的发言人角色 |
365
+ | `maxItems` | `number` | `2` | 最多保留的字幕条数,超过后清理最旧条目 |
366
+
367
+ `IviSubtitleItem` 包含 `id`、`role`、`lifecycle`、`status`、`text`、`transcript`、`displayText`、`timestamp`、`updatedAt`、`content`、`item`。
368
+
369
+ ```tsx
370
+ function CustomSubtitles({ runtime }: { runtime: IviRuntimeCoordinator | null }) {
371
+ const subtitles = useIviSubtitles(runtime, {
372
+ roles: ["user", "model"],
373
+ maxItems: 5
374
+ });
375
+
376
+ return (
377
+ <div>
378
+ {subtitles.map((item) => (
379
+ <span key={item.id}>{item.displayText}</span>
380
+ ))}
381
+ </div>
382
+ );
383
+ }
384
+ ```
385
+
386
+ 以下 hooks 为 `IVITrackSlot` 内部实现,当前不属于包根公开导出 API。
345
387
 
346
388
  ### `useVolumeMemory`
347
389
 
@@ -349,7 +391,7 @@ function MyOverlay() {
349
391
  function useVolumeMemory(mediaType: IviMediaVolumeType | null): [number, (v: number) => void];
350
392
  ```
351
393
 
352
- 按媒体类型(`"trtc" | "video" | "hls"`)在 `localStorage` 中持久化音量(0–100)。`mediaType` 为 `null` 时不持久化。
394
+ 按媒体类型(`"trtc" | "livekit" | "video" | "hls"`)在 `localStorage` 中持久化音量(0–100)。`mediaType` 为 `null` 时不持久化。
353
395
 
354
396
  ### `useApplyVolumeToSlot`
355
397
 
@@ -362,13 +404,13 @@ function useApplyVolumeToSlot(
362
404
  ): void;
363
405
  ```
364
406
 
365
- 将音量同步应用到容器内带 `data-ivi-slot-role="active"` 属性的 `<video>` / `<audio>` 元素,通过 `MutationObserver` 监听异步插入的媒体(如 TRTC 远端流)。
407
+ 将音量同步应用到容器内带 `data-ivi-slot-role="active"` 属性的 `<video>` / `<audio>` 元素,通过 `MutationObserver` 监听异步插入的媒体(如 TRTC / LiveKit 远端流)。
366
408
 
367
409
  ---
368
410
 
369
411
  ## React 组件
370
412
 
371
- 当前公开导出的 React 组件只有 `IVIStageView` 与 `IVITrackSlot`;当前公开导出的 React hooks 只有 `useManagedIviRuntime` 与 `useIviStageView`。
413
+ 当前公开导出的 React 组件包括 `IVIStageView`、`IVITrackSlot`、`IVITrtcPlayer`、`IVILivekitPlayer` 与 `IVISubtitleOverlay`;当前公开导出的 React hooks 包括 `useManagedIviRuntime`、`useRuntimeState`、`useIviStageView` 与 `useIviSubtitles`。
372
414
 
373
415
  ### `IVIStageView`
374
416
 
@@ -392,20 +434,19 @@ function useApplyVolumeToSlot(
392
434
  | `trackId` | `string` | — | 直接绑定 trackId |
393
435
  | `emptyFallback` | `ReactNode` | — | 无 source 时的兜底内容 |
394
436
  | `renderTrtc` | `(ctx: IviTrackSlotRenderContext) => ReactNode` | — | 自定义 TRTC 渲染 |
395
- | `renderMedia` | `(ctx: IviTrackSlotRenderContext) => ReactNode` | — | 自定义非 TRTC 媒体渲染 |
437
+ | `renderLivekit` | `(ctx: IviTrackSlotRenderContext) => ReactNode` | — | 自定义 LiveKit 远端流渲染 |
438
+ | `renderMedia` | `(ctx: IviTrackSlotRenderContext) => ReactNode` | — | 自定义非 TRTC / LiveKit 媒体渲染 |
396
439
  | `fitStrategy` | `"contain" \| "cover" \| "auto"` | — | 媒体适配策略 |
397
440
  | `adaptToSourceSize` | `boolean` | — | 是否根据 source 尺寸自适应 |
398
- | `background` | `IviTrackSlotBackground` | `"black"` | 媒体空白区域(letterbox/pillarbox)背景模式 |
399
441
  | `showVolumeControl` | `boolean` | — | 是否显示音量控制浮层 |
400
442
  | `volumeControlProps` | — | — | 音量控制自定义配置 |
401
443
  | `showSubtitle` | `boolean` | — | 是否显示字幕浮层 |
402
- | `subtitleProps` | | — | 字幕自定义配置 |
444
+ | `subtitleProps` | `Omit<IVISubtitleOverlayProps, "runtime">` | — | 字幕自定义配置 |
403
445
  | `trtcPlayerProps` | — | — | TRTC 播放器自定义配置 |
446
+ | `livekitPlayerProps` | — | — | LiveKit 播放器自定义配置 |
404
447
  | `videoProps` / `imageProps` | — | — | 透传给原生 `<video>` / `<img>` |
405
448
  | `className` / `style` | — | — | 容器样式 |
406
449
 
407
- `IviTrackSlotBackground` 支持的值:`"black"` | `"white"` | `"transparent"` | `{ color: string }` | `"blur"` | `{ blur: "live" | "static" }`
408
-
409
450
  `IviTrackSlotRenderContext`:
410
451
 
411
452
  ```ts
@@ -417,7 +458,7 @@ interface IviTrackSlotRenderContext {
417
458
  }
418
459
  ```
419
460
 
420
- 以下组件为 `IVITrackSlot` 依赖的内部实现,当前不属于公开导出 API。
461
+ 以下远端播放器可由 `IVITrackSlot` 默认使用,也可在业务侧按需直接使用。
421
462
 
422
463
  ### `IVITrtcPlayer`
423
464
 
@@ -425,7 +466,21 @@ TRTC 远端流播放器,自动以 audience 身份入会并订阅远端流。
425
466
 
426
467
  | Prop | 类型 | 说明 |
427
468
  |------|------|------|
428
- | `trtc` | TRTC 实例 | TRTC SDK 实例 |
469
+ | `trtc` | `IviSourcePlaybackTrtc` | TRTC 拉流配置 |
470
+ | `sourceId` | `string` | source ID |
471
+ | `runtime` | `IviRuntimeCoordinator` | runtime 实例 |
472
+ | `loadingFallback` | `ReactNode` | 加载中兜底 |
473
+ | `errorFallback` | `ReactNode` | 错误兜底 |
474
+ | `muted` | `boolean` | 是否静音 |
475
+ | `className` / `style` | — | 容器样式 |
476
+
477
+ ### `IVILivekitPlayer`
478
+
479
+ LiveKit 远端音视频播放器,挂载后加入房间并订阅远端 tracks。`ivi-frontend-sdk` 只负责拉取和播放远端音视频流,不再发布用户麦克风;麦克风采集 / ASR 数据链路请使用 `@vivix-ai/ivi-sdk-ts/transports/livekit-browser` 或业务侧 transport。
480
+
481
+ | Prop | 类型 | 说明 |
482
+ |------|------|------|
483
+ | `livekit` | LiveKit playback 配置 | 包含 `ws_url`、`token`,以及可选 `room` / `identity` |
429
484
  | `sourceId` | `string` | source ID |
430
485
  | `runtime` | `IviRuntimeCoordinator` | runtime 实例 |
431
486
  | `loadingFallback` | `ReactNode` | 加载中兜底 |
@@ -433,9 +488,9 @@ TRTC 远端流播放器,自动以 audience 身份入会并订阅远端流。
433
488
  | `muted` | `boolean` | 是否静音 |
434
489
  | `className` / `style` | — | 容器样式 |
435
490
 
436
- ### `IVIHlsVideo`
491
+ ### `IVIHlsVideo`(内部组件)
437
492
 
438
- HLS 流播放器(基于 `hls.js`),用于 `.m3u8` 地址播放。辅助函数 `isM3u8Url(url)` 可判断 URL 是否为 m3u8。
493
+ HLS 流播放器(基于 `hls.js`),由 `IVITrackSlot` 内部用于 `.m3u8` 地址播放;当前不从包根公开导出。
439
494
 
440
495
  | Prop | 类型 | 说明 |
441
496
  |------|------|------|
@@ -445,18 +500,37 @@ HLS 流播放器(基于 `hls.js`),用于 `.m3u8` 地址播放。辅助函
445
500
  | `aggressivePreload` | `boolean` | 激进预加载模式 |
446
501
  | `paused` | `boolean` | 是否暂停 |
447
502
 
448
- > 隐藏原生控件(包括进度条):SDK 未提供单独隐藏进度条的开关,HTML5 `<video>` 也不支持只隐藏 timeline。可通过 `videoProps.controls = false` 关闭整套原生控件,适用于 `IVIHlsVideo` 与 `IVITrackSlot`:
503
+ > 隐藏原生控件(包括进度条):SDK 未提供单独隐藏进度条的开关,HTML5 `<video>` 也不支持只隐藏 timeline。可通过 `videoProps.controls = false` 关闭整套原生控件,适用于 `IVITrackSlot`:
449
504
  >
450
505
  > ```tsx
451
- > <IVIHlsVideo url={url} videoProps={{ controls: false }} />
452
506
  > <IVITrackSlot slot="main" videoProps={{ controls: false }} />
453
507
  > ```
454
508
  >
455
509
  > 若需“保留播放/音量,仅隐藏进度条”,请在上层自行渲染自定义控制栏。
456
510
 
511
+ ### `IVIFlvVideo`
512
+
513
+ FLV 流播放器(基于 `xgplayer` + `xgplayer-flv`),用于 `.flv` 地址播放。`IVITrackSlot` 会按 URL 后缀自动选用。辅助函数 `isFlvUrl(url)` 可判断 URL 是否为 flv。
514
+
515
+ 使用前需安装 peer 依赖:
516
+
517
+ ```bash
518
+ npm install xgplayer xgplayer-flv
519
+ ```
520
+
521
+ | Prop | 类型 | 说明 |
522
+ |------|------|------|
523
+ | `url` | `string` | FLV 播放地址 |
524
+ | `videoProps` | — | 透传 muted / controls / onEnded 等语义 |
525
+ | `style` | — | 容器样式 |
526
+ | `isLive` | `boolean` | 是否直播,默认 `true` |
527
+ | `paused` | `boolean` | 是否暂停(standby 预加载) |
528
+
529
+ > 直播 FLV 通常不会触发 `ended`,切换 source 时请使用定时模式而非「播放完毕」。
530
+
457
531
  ### `IVIVolumeControl`
458
532
 
459
- 音量控制浮层组件。
533
+ 音量控制浮层组件,由 `IVITrackSlot` 在 `showVolumeControl` 开启时内部使用;当前不从包根公开导出。
460
534
 
461
535
  | Prop | 类型 | 说明 |
462
536
  |------|------|------|
@@ -468,13 +542,14 @@ HLS 流播放器(基于 `hls.js`),用于 `.m3u8` 地址播放。辅助函
468
542
 
469
543
  ### `IVISubtitleOverlay`
470
544
 
471
- 字幕浮层组件,展示对话条目流式字幕。
545
+ 预制字幕浮层组件,内部通过 `useIviSubtitles` 监听 runtime 的 conversation / response 事件并展示字幕。
472
546
 
473
547
  | Prop | 类型 | 默认值 | 说明 |
474
548
  |------|------|--------|------|
475
- | `conversations` | `IviRuntimeConversationItem[]` | — | 会话条目列表 |
476
- | `maxVisible` | `number` | `2` | 同时可见的最大条目数 |
477
- | `dismissAfterMs` | `number` | `5000` | 条目完成后自动消失毫秒数 |
549
+ | `runtime` | `IviRuntimeCoordinator \| null` | — | 字幕来源 runtime |
550
+ | `roles` | `IviSubtitleRole \| IviSubtitleRole[]` | `"user"` | 要展示的发言人角色 |
551
+ | `maxItems` | `number` | `2` | 最多保留的字幕条数,超过后清理最旧条目 |
552
+ | `maxVisible` | `number` | — | 已废弃,兼容旧字段;请使用 `maxItems` |
478
553
  | `subtitleStyle` | `IVISubtitleOverlayStyle` | — | 样式配置 |
479
554
  | `className` / `style` | — | — | 样式 |
480
555
 
@@ -493,7 +568,7 @@ HLS 流播放器(基于 `hls.js`),用于 `.m3u8` 地址播放。辅助函
493
568
  | `sendSessionSourcePlaybackCompleted(sourceId, trackId?)` | 上报 source 播放完成 |
494
569
  | `sendConversationList()` | 请求对话列表 |
495
570
  | `sendConversationItemCreate(item)` | 创建对话条目 |
496
- | `sendConversationUserText(text, itemId?)` | 发送用户文本,返回 `Promise<string>`,resolve 为最终 itemId |
571
+ | `sendUserText(text, itemId?)` | 发送用户文本 |
497
572
  | `sendResponseCreate(streamId?, response?)` | 触发模型回复;`streamId` 可选,省略时使用 session 级配置 |
498
573
  | `sendResponseCreateByItemId(itemId, streamId?, response?)` | 基于条目 ID 触发模型回复 |
499
574
 
@@ -549,13 +624,13 @@ npm run test
549
624
  仓库提供版本提升脚本,执行前要求工作区干净:
550
625
 
551
626
  ```bash
552
- npm run release:version -- 0.2.2
627
+ npm run release:version -- 0.3.0
553
628
  ```
554
629
 
555
630
  脚本会同步更新 `package.json` / `package-lock.json`,提交:
556
631
 
557
632
  ```text
558
- chore: update package version to 0.2.2
633
+ chore: update package version to 0.3.0
559
634
  ```
560
635
 
561
- 并创建 tag:`v0.2.2`。
636
+ 并创建 tag:`v0.3.0`。