@vivix-ai/ivi-frontend-sdk 0.3.2 → 0.3.4
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 +7 -0
- package/dist/index.cjs +153 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -3
- package/dist/index.d.ts +35 -3
- package/dist/index.js +153 -38
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -72,6 +72,21 @@ interface IviRuntimeTrtcEvent {
|
|
|
72
72
|
streamType?: unknown;
|
|
73
73
|
}
|
|
74
74
|
type IviRuntimeTrtcEventListener = (event: IviRuntimeTrtcEvent) => void;
|
|
75
|
+
type IviRuntimeTrtcAIDenoiserMode = "normal" | "far_field_reduction";
|
|
76
|
+
interface IviRuntimeTrtcAIDenoiserOptions {
|
|
77
|
+
/**
|
|
78
|
+
* 是否启用 TRTC AIDenoiser 插件,默认 true。
|
|
79
|
+
*/
|
|
80
|
+
enabled?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* 降噪模式,默认 "normal"。
|
|
83
|
+
*/
|
|
84
|
+
mode?: IviRuntimeTrtcAIDenoiserMode;
|
|
85
|
+
/**
|
|
86
|
+
* TRTC AIDenoiser 资源路径;未配置时使用 TRTC SDK 默认加载逻辑。
|
|
87
|
+
*/
|
|
88
|
+
assetsPath?: string;
|
|
89
|
+
}
|
|
75
90
|
type IviRuntimeConversationLifecycle = "added" | "done";
|
|
76
91
|
type IviRuntimeConversationStatus = "in_progress" | "completed" | "incomplete";
|
|
77
92
|
interface IviRuntimeConversationItem {
|
|
@@ -103,6 +118,10 @@ interface IviRuntimeCoordinatorConfig {
|
|
|
103
118
|
* TRTC SDK 原始事件回调;可用于业务监听远端音视频可用性等底层事件。
|
|
104
119
|
*/
|
|
105
120
|
onTrtcEvent?: IviRuntimeTrtcEventListener;
|
|
121
|
+
/**
|
|
122
|
+
* TRTC SDK AIDenoiser 降噪配置。默认开启;传 false 可关闭。
|
|
123
|
+
*/
|
|
124
|
+
trtcAIDenoiser?: boolean | IviRuntimeTrtcAIDenoiserOptions;
|
|
106
125
|
}
|
|
107
126
|
/**
|
|
108
127
|
* 用户输入触发回复链路配置。
|
|
@@ -177,9 +196,11 @@ type TrtcSourceListener = (snapshot: TrtcSourceSnapshot) => void;
|
|
|
177
196
|
declare class TrtcSourceManager {
|
|
178
197
|
private readonly onLog?;
|
|
179
198
|
private readonly onTrtcEvent?;
|
|
199
|
+
private readonly aiDenoiser?;
|
|
180
200
|
private readonly sessions;
|
|
201
|
+
private readonly sourceSessionKeys;
|
|
181
202
|
private readonly listeners;
|
|
182
|
-
constructor(onLog?: IviRuntimeLogCallback | undefined, onTrtcEvent?: IviRuntimeTrtcEventListener | undefined);
|
|
203
|
+
constructor(onLog?: IviRuntimeLogCallback | undefined, onTrtcEvent?: IviRuntimeTrtcEventListener | undefined, aiDenoiser?: (boolean | IviRuntimeTrtcAIDenoiserOptions) | undefined);
|
|
183
204
|
/**
|
|
184
205
|
* 将 runtime 当前 sources 与 TRTC 会话池对齐:
|
|
185
206
|
* - 对 ready + trtc 的 source 进行 upsert(必要时建立连接)
|
|
@@ -190,7 +211,7 @@ declare class TrtcSourceManager {
|
|
|
190
211
|
* 按 sourceId 注册/更新 TRTC 配置。
|
|
191
212
|
* 若配置发生变化,会先销毁旧会话再按新参数重建连接。
|
|
192
213
|
*/
|
|
193
|
-
upsertSource(sourceId: string, trtc: IviSourcePlaybackTrtc): void;
|
|
214
|
+
upsertSource(sourceId: string, trtc: IviSourcePlaybackTrtc, aiDenoiser?: boolean | IviRuntimeTrtcAIDenoiserOptions): void;
|
|
194
215
|
/**
|
|
195
216
|
* 删除指定 source 的 TRTC 会话并释放连接资源。
|
|
196
217
|
* 该操作通常由 source.deleted 或会话重置触发。
|
|
@@ -218,6 +239,11 @@ declare class TrtcSourceManager {
|
|
|
218
239
|
attachView(sourceId: string, viewId: string, container: HTMLElement, muted: boolean): Promise<void>;
|
|
219
240
|
detachView(sourceId: string, viewId: string): void;
|
|
220
241
|
updateViewMuted(sourceId: string, viewId: string, muted: boolean): void;
|
|
242
|
+
private unlinkSourceFromSession;
|
|
243
|
+
private getSession;
|
|
244
|
+
private snapshotFromSession;
|
|
245
|
+
private emitSessionSnapshot;
|
|
246
|
+
private emitSessionTrtcEvent;
|
|
221
247
|
private createSession;
|
|
222
248
|
/**
|
|
223
249
|
* 懒连接入口:同一会话只允许一次并发 connectPromise。
|
|
@@ -232,6 +258,7 @@ declare class TrtcSourceManager {
|
|
|
232
258
|
* - 至少一个 view 需出声 -> 对可用远端用户解除静音
|
|
233
259
|
*/
|
|
234
260
|
private applyAudioPolicy;
|
|
261
|
+
private applyAIDenoiserPolicy;
|
|
235
262
|
/**
|
|
236
263
|
* 销毁单个 source 会话:
|
|
237
264
|
* 解绑事件、停止远端视频、退出房间并销毁客户端。
|
|
@@ -546,6 +573,11 @@ interface IVITrtcPlayerProps {
|
|
|
546
573
|
loadingFallback?: ReactNode;
|
|
547
574
|
errorFallback?: ReactNode;
|
|
548
575
|
muted?: boolean;
|
|
576
|
+
/**
|
|
577
|
+
* 独立使用 IVITrtcPlayer(未传 runtime)时的 TRTC AIDenoiser 降噪配置。
|
|
578
|
+
* 默认开启;传 false 可关闭。
|
|
579
|
+
*/
|
|
580
|
+
trtcAIDenoiser?: boolean | IviRuntimeTrtcAIDenoiserOptions;
|
|
549
581
|
}
|
|
550
582
|
/**
|
|
551
583
|
* 默认 TRTC 播放器:挂载即加入房间并拉流,连接由 TrtcSourceManager 统一复用。
|
|
@@ -724,4 +756,4 @@ declare function useManagedIviRuntime(config: IviManagedRuntimeConfig): IviRunti
|
|
|
724
756
|
|
|
725
757
|
declare function useIviStageView(): IviStageViewContextValue;
|
|
726
758
|
|
|
727
|
-
export { EMPTY_RUNTIME_STATE, IVILivekitPlayer, type IVILivekitPlayerProps, IVIStageView, type IVIStageViewProps, IVISubtitleOverlay, type IVISubtitleOverlayProps, type IVISubtitleOverlayStyle, IVITrackSlot, type IVITrackSlotProps, IVITrtcPlayer, type IVITrtcPlayerProps, type IviFrontendClientConfig, IviFrontendSdk, type IviManagedRuntimeConfig, type IviManagedRuntimeLogCallback, type IviManagedRuntimeLogEntry, type IviManagedRuntimeLogLevel, type IviManagedRuntimeLogSource, type IviRuntimeConversationItem, type IviRuntimeConversationLifecycle, type IviRuntimeConversationStatus, IviRuntimeCoordinator, type IviRuntimeCoordinatorConfig, IviRuntimeDispatcher, type IviRuntimeDispatcherConfig, type IviRuntimeEventListener, type IviRuntimeLogCallback, type IviRuntimeLogEntry, type IviRuntimeLogLevel, type IviRuntimeSource, type IviRuntimeSourcePreloadState, type IviRuntimeState, type IviRuntimeStatus, type IviRuntimeStream, type IviRuntimeTrtcEvent, type IviRuntimeTrtcEventListener, type IviRuntimeTrtcEventType, type IviRuntimeUserTextToResponseCallbacks, type IviRuntimeUserTextToResponseOptions, type IviRuntimeUserTextToResponseResult, type IviSourcePlaybackLivekit, type IviSourcePlaybackLivekitDescriptor, type IviStageSlotBinding, type IviStageViewContextValue, type IviSubtitleItem, type IviSubtitleRole, type IviUseSubtitlesOptions, LivekitSourceManager, TrtcSourceManager, isLivekitSourcePlayback, isReadyLivekitRuntimeSource, isSameLivekitConfig, useIviStageView, useIviSubtitles, useManagedIviRuntime, useRuntimeState };
|
|
759
|
+
export { EMPTY_RUNTIME_STATE, IVILivekitPlayer, type IVILivekitPlayerProps, IVIStageView, type IVIStageViewProps, IVISubtitleOverlay, type IVISubtitleOverlayProps, type IVISubtitleOverlayStyle, IVITrackSlot, type IVITrackSlotProps, IVITrtcPlayer, type IVITrtcPlayerProps, type IviFrontendClientConfig, IviFrontendSdk, type IviManagedRuntimeConfig, type IviManagedRuntimeLogCallback, type IviManagedRuntimeLogEntry, type IviManagedRuntimeLogLevel, type IviManagedRuntimeLogSource, type IviRuntimeConversationItem, type IviRuntimeConversationLifecycle, type IviRuntimeConversationStatus, IviRuntimeCoordinator, type IviRuntimeCoordinatorConfig, IviRuntimeDispatcher, type IviRuntimeDispatcherConfig, type IviRuntimeEventListener, type IviRuntimeLogCallback, type IviRuntimeLogEntry, type IviRuntimeLogLevel, type IviRuntimeSource, type IviRuntimeSourcePreloadState, type IviRuntimeState, type IviRuntimeStatus, type IviRuntimeStream, type IviRuntimeTrtcAIDenoiserMode, type IviRuntimeTrtcAIDenoiserOptions, type IviRuntimeTrtcEvent, type IviRuntimeTrtcEventListener, type IviRuntimeTrtcEventType, type IviRuntimeUserTextToResponseCallbacks, type IviRuntimeUserTextToResponseOptions, type IviRuntimeUserTextToResponseResult, type IviSourcePlaybackLivekit, type IviSourcePlaybackLivekitDescriptor, type IviStageSlotBinding, type IviStageViewContextValue, type IviSubtitleItem, type IviSubtitleRole, type IviUseSubtitlesOptions, LivekitSourceManager, TrtcSourceManager, isLivekitSourcePlayback, isReadyLivekitRuntimeSource, isSameLivekitConfig, useIviStageView, useIviSubtitles, useManagedIviRuntime, useRuntimeState };
|
package/dist/index.d.ts
CHANGED
|
@@ -72,6 +72,21 @@ interface IviRuntimeTrtcEvent {
|
|
|
72
72
|
streamType?: unknown;
|
|
73
73
|
}
|
|
74
74
|
type IviRuntimeTrtcEventListener = (event: IviRuntimeTrtcEvent) => void;
|
|
75
|
+
type IviRuntimeTrtcAIDenoiserMode = "normal" | "far_field_reduction";
|
|
76
|
+
interface IviRuntimeTrtcAIDenoiserOptions {
|
|
77
|
+
/**
|
|
78
|
+
* 是否启用 TRTC AIDenoiser 插件,默认 true。
|
|
79
|
+
*/
|
|
80
|
+
enabled?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* 降噪模式,默认 "normal"。
|
|
83
|
+
*/
|
|
84
|
+
mode?: IviRuntimeTrtcAIDenoiserMode;
|
|
85
|
+
/**
|
|
86
|
+
* TRTC AIDenoiser 资源路径;未配置时使用 TRTC SDK 默认加载逻辑。
|
|
87
|
+
*/
|
|
88
|
+
assetsPath?: string;
|
|
89
|
+
}
|
|
75
90
|
type IviRuntimeConversationLifecycle = "added" | "done";
|
|
76
91
|
type IviRuntimeConversationStatus = "in_progress" | "completed" | "incomplete";
|
|
77
92
|
interface IviRuntimeConversationItem {
|
|
@@ -103,6 +118,10 @@ interface IviRuntimeCoordinatorConfig {
|
|
|
103
118
|
* TRTC SDK 原始事件回调;可用于业务监听远端音视频可用性等底层事件。
|
|
104
119
|
*/
|
|
105
120
|
onTrtcEvent?: IviRuntimeTrtcEventListener;
|
|
121
|
+
/**
|
|
122
|
+
* TRTC SDK AIDenoiser 降噪配置。默认开启;传 false 可关闭。
|
|
123
|
+
*/
|
|
124
|
+
trtcAIDenoiser?: boolean | IviRuntimeTrtcAIDenoiserOptions;
|
|
106
125
|
}
|
|
107
126
|
/**
|
|
108
127
|
* 用户输入触发回复链路配置。
|
|
@@ -177,9 +196,11 @@ type TrtcSourceListener = (snapshot: TrtcSourceSnapshot) => void;
|
|
|
177
196
|
declare class TrtcSourceManager {
|
|
178
197
|
private readonly onLog?;
|
|
179
198
|
private readonly onTrtcEvent?;
|
|
199
|
+
private readonly aiDenoiser?;
|
|
180
200
|
private readonly sessions;
|
|
201
|
+
private readonly sourceSessionKeys;
|
|
181
202
|
private readonly listeners;
|
|
182
|
-
constructor(onLog?: IviRuntimeLogCallback | undefined, onTrtcEvent?: IviRuntimeTrtcEventListener | undefined);
|
|
203
|
+
constructor(onLog?: IviRuntimeLogCallback | undefined, onTrtcEvent?: IviRuntimeTrtcEventListener | undefined, aiDenoiser?: (boolean | IviRuntimeTrtcAIDenoiserOptions) | undefined);
|
|
183
204
|
/**
|
|
184
205
|
* 将 runtime 当前 sources 与 TRTC 会话池对齐:
|
|
185
206
|
* - 对 ready + trtc 的 source 进行 upsert(必要时建立连接)
|
|
@@ -190,7 +211,7 @@ declare class TrtcSourceManager {
|
|
|
190
211
|
* 按 sourceId 注册/更新 TRTC 配置。
|
|
191
212
|
* 若配置发生变化,会先销毁旧会话再按新参数重建连接。
|
|
192
213
|
*/
|
|
193
|
-
upsertSource(sourceId: string, trtc: IviSourcePlaybackTrtc): void;
|
|
214
|
+
upsertSource(sourceId: string, trtc: IviSourcePlaybackTrtc, aiDenoiser?: boolean | IviRuntimeTrtcAIDenoiserOptions): void;
|
|
194
215
|
/**
|
|
195
216
|
* 删除指定 source 的 TRTC 会话并释放连接资源。
|
|
196
217
|
* 该操作通常由 source.deleted 或会话重置触发。
|
|
@@ -218,6 +239,11 @@ declare class TrtcSourceManager {
|
|
|
218
239
|
attachView(sourceId: string, viewId: string, container: HTMLElement, muted: boolean): Promise<void>;
|
|
219
240
|
detachView(sourceId: string, viewId: string): void;
|
|
220
241
|
updateViewMuted(sourceId: string, viewId: string, muted: boolean): void;
|
|
242
|
+
private unlinkSourceFromSession;
|
|
243
|
+
private getSession;
|
|
244
|
+
private snapshotFromSession;
|
|
245
|
+
private emitSessionSnapshot;
|
|
246
|
+
private emitSessionTrtcEvent;
|
|
221
247
|
private createSession;
|
|
222
248
|
/**
|
|
223
249
|
* 懒连接入口:同一会话只允许一次并发 connectPromise。
|
|
@@ -232,6 +258,7 @@ declare class TrtcSourceManager {
|
|
|
232
258
|
* - 至少一个 view 需出声 -> 对可用远端用户解除静音
|
|
233
259
|
*/
|
|
234
260
|
private applyAudioPolicy;
|
|
261
|
+
private applyAIDenoiserPolicy;
|
|
235
262
|
/**
|
|
236
263
|
* 销毁单个 source 会话:
|
|
237
264
|
* 解绑事件、停止远端视频、退出房间并销毁客户端。
|
|
@@ -546,6 +573,11 @@ interface IVITrtcPlayerProps {
|
|
|
546
573
|
loadingFallback?: ReactNode;
|
|
547
574
|
errorFallback?: ReactNode;
|
|
548
575
|
muted?: boolean;
|
|
576
|
+
/**
|
|
577
|
+
* 独立使用 IVITrtcPlayer(未传 runtime)时的 TRTC AIDenoiser 降噪配置。
|
|
578
|
+
* 默认开启;传 false 可关闭。
|
|
579
|
+
*/
|
|
580
|
+
trtcAIDenoiser?: boolean | IviRuntimeTrtcAIDenoiserOptions;
|
|
549
581
|
}
|
|
550
582
|
/**
|
|
551
583
|
* 默认 TRTC 播放器:挂载即加入房间并拉流,连接由 TrtcSourceManager 统一复用。
|
|
@@ -724,4 +756,4 @@ declare function useManagedIviRuntime(config: IviManagedRuntimeConfig): IviRunti
|
|
|
724
756
|
|
|
725
757
|
declare function useIviStageView(): IviStageViewContextValue;
|
|
726
758
|
|
|
727
|
-
export { EMPTY_RUNTIME_STATE, IVILivekitPlayer, type IVILivekitPlayerProps, IVIStageView, type IVIStageViewProps, IVISubtitleOverlay, type IVISubtitleOverlayProps, type IVISubtitleOverlayStyle, IVITrackSlot, type IVITrackSlotProps, IVITrtcPlayer, type IVITrtcPlayerProps, type IviFrontendClientConfig, IviFrontendSdk, type IviManagedRuntimeConfig, type IviManagedRuntimeLogCallback, type IviManagedRuntimeLogEntry, type IviManagedRuntimeLogLevel, type IviManagedRuntimeLogSource, type IviRuntimeConversationItem, type IviRuntimeConversationLifecycle, type IviRuntimeConversationStatus, IviRuntimeCoordinator, type IviRuntimeCoordinatorConfig, IviRuntimeDispatcher, type IviRuntimeDispatcherConfig, type IviRuntimeEventListener, type IviRuntimeLogCallback, type IviRuntimeLogEntry, type IviRuntimeLogLevel, type IviRuntimeSource, type IviRuntimeSourcePreloadState, type IviRuntimeState, type IviRuntimeStatus, type IviRuntimeStream, type IviRuntimeTrtcEvent, type IviRuntimeTrtcEventListener, type IviRuntimeTrtcEventType, type IviRuntimeUserTextToResponseCallbacks, type IviRuntimeUserTextToResponseOptions, type IviRuntimeUserTextToResponseResult, type IviSourcePlaybackLivekit, type IviSourcePlaybackLivekitDescriptor, type IviStageSlotBinding, type IviStageViewContextValue, type IviSubtitleItem, type IviSubtitleRole, type IviUseSubtitlesOptions, LivekitSourceManager, TrtcSourceManager, isLivekitSourcePlayback, isReadyLivekitRuntimeSource, isSameLivekitConfig, useIviStageView, useIviSubtitles, useManagedIviRuntime, useRuntimeState };
|
|
759
|
+
export { EMPTY_RUNTIME_STATE, IVILivekitPlayer, type IVILivekitPlayerProps, IVIStageView, type IVIStageViewProps, IVISubtitleOverlay, type IVISubtitleOverlayProps, type IVISubtitleOverlayStyle, IVITrackSlot, type IVITrackSlotProps, IVITrtcPlayer, type IVITrtcPlayerProps, type IviFrontendClientConfig, IviFrontendSdk, type IviManagedRuntimeConfig, type IviManagedRuntimeLogCallback, type IviManagedRuntimeLogEntry, type IviManagedRuntimeLogLevel, type IviManagedRuntimeLogSource, type IviRuntimeConversationItem, type IviRuntimeConversationLifecycle, type IviRuntimeConversationStatus, IviRuntimeCoordinator, type IviRuntimeCoordinatorConfig, IviRuntimeDispatcher, type IviRuntimeDispatcherConfig, type IviRuntimeEventListener, type IviRuntimeLogCallback, type IviRuntimeLogEntry, type IviRuntimeLogLevel, type IviRuntimeSource, type IviRuntimeSourcePreloadState, type IviRuntimeState, type IviRuntimeStatus, type IviRuntimeStream, type IviRuntimeTrtcAIDenoiserMode, type IviRuntimeTrtcAIDenoiserOptions, type IviRuntimeTrtcEvent, type IviRuntimeTrtcEventListener, type IviRuntimeTrtcEventType, type IviRuntimeUserTextToResponseCallbacks, type IviRuntimeUserTextToResponseOptions, type IviRuntimeUserTextToResponseResult, type IviSourcePlaybackLivekit, type IviSourcePlaybackLivekitDescriptor, type IviStageSlotBinding, type IviStageViewContextValue, type IviSubtitleItem, type IviSubtitleRole, type IviUseSubtitlesOptions, LivekitSourceManager, TrtcSourceManager, isLivekitSourcePlayback, isReadyLivekitRuntimeSource, isSameLivekitConfig, useIviStageView, useIviSubtitles, useManagedIviRuntime, useRuntimeState };
|
package/dist/index.js
CHANGED
|
@@ -1105,11 +1105,17 @@ var ConversationManager = class {
|
|
|
1105
1105
|
|
|
1106
1106
|
// src/runtime/managers/trtc-source-manager.ts
|
|
1107
1107
|
var TAG = "[IVI-TRTC]";
|
|
1108
|
+
var DEFAULT_DENOISER_OPTIONS = {
|
|
1109
|
+
enabled: true,
|
|
1110
|
+
mode: "normal"
|
|
1111
|
+
};
|
|
1108
1112
|
var TrtcSourceManager = class {
|
|
1109
|
-
constructor(onLog, onTrtcEvent) {
|
|
1113
|
+
constructor(onLog, onTrtcEvent, aiDenoiser) {
|
|
1110
1114
|
this.onLog = onLog;
|
|
1111
1115
|
this.onTrtcEvent = onTrtcEvent;
|
|
1116
|
+
this.aiDenoiser = aiDenoiser;
|
|
1112
1117
|
this.sessions = /* @__PURE__ */ new Map();
|
|
1118
|
+
this.sourceSessionKeys = /* @__PURE__ */ new Map();
|
|
1113
1119
|
this.listeners = /* @__PURE__ */ new Map();
|
|
1114
1120
|
}
|
|
1115
1121
|
/**
|
|
@@ -1118,15 +1124,16 @@ var TrtcSourceManager = class {
|
|
|
1118
1124
|
* - 清理已不在 runtime 中的会话(释放资源)
|
|
1119
1125
|
*/
|
|
1120
1126
|
syncRuntimeSources(sources) {
|
|
1121
|
-
const
|
|
1127
|
+
const trtcSourceIds = /* @__PURE__ */ new Set();
|
|
1122
1128
|
sources.forEach((source, sourceId) => {
|
|
1123
1129
|
if (!isRuntimeTrtcSource(source)) {
|
|
1124
1130
|
return;
|
|
1125
1131
|
}
|
|
1132
|
+
trtcSourceIds.add(sourceId);
|
|
1126
1133
|
this.upsertSource(sourceId, source.playback.trtc);
|
|
1127
1134
|
});
|
|
1128
|
-
this.
|
|
1129
|
-
if (!
|
|
1135
|
+
Array.from(this.sourceSessionKeys.keys()).forEach((sourceId) => {
|
|
1136
|
+
if (!trtcSourceIds.has(sourceId)) {
|
|
1130
1137
|
this.removeSource(sourceId);
|
|
1131
1138
|
}
|
|
1132
1139
|
});
|
|
@@ -1135,22 +1142,29 @@ var TrtcSourceManager = class {
|
|
|
1135
1142
|
* 按 sourceId 注册/更新 TRTC 配置。
|
|
1136
1143
|
* 若配置发生变化,会先销毁旧会话再按新参数重建连接。
|
|
1137
1144
|
*/
|
|
1138
|
-
upsertSource(sourceId, trtc) {
|
|
1139
|
-
const existing = this.
|
|
1140
|
-
if (
|
|
1141
|
-
this.log("info", `\u65B0\u5EFA\u4F1A\u8BDD source=${sourceId} room=${getTrtcString(trtc, "room_id")} user=${getTrtcString(trtc, "user_id")}`);
|
|
1142
|
-
const session2 = this.createSession(sourceId, trtc);
|
|
1143
|
-
this.sessions.set(sourceId, session2);
|
|
1144
|
-
void this.ensureConnected(session2);
|
|
1145
|
+
upsertSource(sourceId, trtc, aiDenoiser) {
|
|
1146
|
+
const existing = this.getSession(sourceId);
|
|
1147
|
+
if (existing && isSameTrtcConfig(existing.trtc, trtc) && isSameAIDenoiserOptions(existing.aiDenoiser, aiDenoiser)) {
|
|
1145
1148
|
return;
|
|
1146
1149
|
}
|
|
1147
|
-
if (
|
|
1150
|
+
if (existing) {
|
|
1151
|
+
this.log("info", `\u914D\u7F6E\u53D8\u66F4\uFF0C\u91CD\u5EFA\u4F1A\u8BDD source=${sourceId} room=${getTrtcString(trtc, "room_id")}`);
|
|
1152
|
+
this.unlinkSourceFromSession(sourceId, existing);
|
|
1153
|
+
}
|
|
1154
|
+
const sessionKey = buildTrtcSessionKey(trtc, aiDenoiser);
|
|
1155
|
+
const reusable = this.sessions.get(sessionKey);
|
|
1156
|
+
if (reusable) {
|
|
1157
|
+
this.log("info", `\u590D\u7528\u4F1A\u8BDD source=${sourceId} room=${getTrtcString(trtc, "room_id")} user=${getTrtcString(trtc, "user_id")}`);
|
|
1158
|
+
reusable.sourceIds.add(sourceId);
|
|
1159
|
+
this.sourceSessionKeys.set(sourceId, sessionKey);
|
|
1160
|
+
this.emitSnapshot(sourceId, this.snapshotFromSession(reusable));
|
|
1161
|
+
void this.ensureConnected(reusable);
|
|
1148
1162
|
return;
|
|
1149
1163
|
}
|
|
1150
|
-
this.log("info", `\
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
this.
|
|
1164
|
+
this.log("info", `\u65B0\u5EFA\u4F1A\u8BDD source=${sourceId} room=${getTrtcString(trtc, "room_id")} user=${getTrtcString(trtc, "user_id")}`);
|
|
1165
|
+
const session = this.createSession(sourceId, trtc, aiDenoiser);
|
|
1166
|
+
this.sessions.set(session.sessionKey, session);
|
|
1167
|
+
this.sourceSessionKeys.set(sourceId, session.sessionKey);
|
|
1154
1168
|
void this.ensureConnected(session);
|
|
1155
1169
|
}
|
|
1156
1170
|
/**
|
|
@@ -1158,13 +1172,12 @@ var TrtcSourceManager = class {
|
|
|
1158
1172
|
* 该操作通常由 source.deleted 或会话重置触发。
|
|
1159
1173
|
*/
|
|
1160
1174
|
removeSource(sourceId) {
|
|
1161
|
-
const session = this.
|
|
1175
|
+
const session = this.getSession(sourceId);
|
|
1162
1176
|
if (!session) {
|
|
1163
1177
|
return;
|
|
1164
1178
|
}
|
|
1165
1179
|
this.log("info", `\u79FB\u9664\u4F1A\u8BDD source=${sourceId}`);
|
|
1166
|
-
this.
|
|
1167
|
-
void this.disposeSession(session);
|
|
1180
|
+
this.unlinkSourceFromSession(sourceId, session);
|
|
1168
1181
|
this.emitSnapshot(sourceId, {
|
|
1169
1182
|
status: "idle"
|
|
1170
1183
|
});
|
|
@@ -1174,6 +1187,7 @@ var TrtcSourceManager = class {
|
|
|
1174
1187
|
this.log("info", `\u91CD\u7F6E\u5168\u90E8\u4F1A\u8BDD count=${this.sessions.size}`);
|
|
1175
1188
|
const sessions = Array.from(this.sessions.values());
|
|
1176
1189
|
this.sessions.clear();
|
|
1190
|
+
this.sourceSessionKeys.clear();
|
|
1177
1191
|
sessions.forEach((session) => {
|
|
1178
1192
|
void this.disposeSession(session);
|
|
1179
1193
|
});
|
|
@@ -1196,7 +1210,7 @@ var TrtcSourceManager = class {
|
|
|
1196
1210
|
};
|
|
1197
1211
|
}
|
|
1198
1212
|
getSnapshot(sourceId) {
|
|
1199
|
-
const session = this.
|
|
1213
|
+
const session = this.getSession(sourceId);
|
|
1200
1214
|
if (!session) {
|
|
1201
1215
|
return {
|
|
1202
1216
|
status: "idle"
|
|
@@ -1211,7 +1225,7 @@ var TrtcSourceManager = class {
|
|
|
1211
1225
|
* 检查指定 source 的 TRTC 会话是否曾收到过 REMOTE_VIDEO_AVAILABLE 事件。
|
|
1212
1226
|
*/
|
|
1213
1227
|
hasRemoteVideoAvailable(sourceId) {
|
|
1214
|
-
const session = this.
|
|
1228
|
+
const session = this.getSession(sourceId);
|
|
1215
1229
|
return session?.hasEverReceivedRemoteVideo ?? false;
|
|
1216
1230
|
}
|
|
1217
1231
|
/**
|
|
@@ -1220,7 +1234,7 @@ var TrtcSourceManager = class {
|
|
|
1220
1234
|
* - 若会话被销毁或超时,返回 false。
|
|
1221
1235
|
*/
|
|
1222
1236
|
waitForRemoteVideoAvailable(sourceId, timeoutMs = 3e4) {
|
|
1223
|
-
const session = this.
|
|
1237
|
+
const session = this.getSession(sourceId);
|
|
1224
1238
|
if (!session) return Promise.resolve(false);
|
|
1225
1239
|
if (session.hasEverReceivedRemoteVideo) return Promise.resolve(true);
|
|
1226
1240
|
return new Promise((resolve) => {
|
|
@@ -1248,11 +1262,12 @@ var TrtcSourceManager = class {
|
|
|
1248
1262
|
* - 应用全局音频策略(根据所有 view 的 muted 汇总)
|
|
1249
1263
|
*/
|
|
1250
1264
|
async attachView(sourceId, viewId, container, muted) {
|
|
1251
|
-
const session = this.
|
|
1265
|
+
const session = this.getSession(sourceId);
|
|
1252
1266
|
if (!session) {
|
|
1253
1267
|
throw new Error(`TRTC source session not found: ${sourceId}`);
|
|
1254
1268
|
}
|
|
1255
1269
|
session.views.set(viewId, {
|
|
1270
|
+
sourceId,
|
|
1256
1271
|
container,
|
|
1257
1272
|
muted,
|
|
1258
1273
|
startedVideoKeys: /* @__PURE__ */ new Set(),
|
|
@@ -1267,15 +1282,18 @@ var TrtcSourceManager = class {
|
|
|
1267
1282
|
await this.applyAudioPolicy(session);
|
|
1268
1283
|
}
|
|
1269
1284
|
detachView(sourceId, viewId) {
|
|
1270
|
-
const session = this.
|
|
1285
|
+
const session = this.getSession(sourceId);
|
|
1271
1286
|
if (!session) {
|
|
1272
1287
|
return;
|
|
1273
1288
|
}
|
|
1274
|
-
session.views.
|
|
1289
|
+
const binding = session.views.get(viewId);
|
|
1290
|
+
if (binding?.sourceId === sourceId) {
|
|
1291
|
+
session.views.delete(viewId);
|
|
1292
|
+
}
|
|
1275
1293
|
void this.applyAudioPolicy(session);
|
|
1276
1294
|
}
|
|
1277
1295
|
updateViewMuted(sourceId, viewId, muted) {
|
|
1278
|
-
const session = this.
|
|
1296
|
+
const session = this.getSession(sourceId);
|
|
1279
1297
|
if (!session) {
|
|
1280
1298
|
return;
|
|
1281
1299
|
}
|
|
@@ -1286,10 +1304,45 @@ var TrtcSourceManager = class {
|
|
|
1286
1304
|
binding.muted = muted;
|
|
1287
1305
|
void this.applyAudioPolicy(session);
|
|
1288
1306
|
}
|
|
1289
|
-
|
|
1307
|
+
unlinkSourceFromSession(sourceId, session) {
|
|
1308
|
+
session.sourceIds.delete(sourceId);
|
|
1309
|
+
this.sourceSessionKeys.delete(sourceId);
|
|
1310
|
+
session.views.forEach((binding, viewId) => {
|
|
1311
|
+
if (binding.sourceId === sourceId) {
|
|
1312
|
+
session.views.delete(viewId);
|
|
1313
|
+
}
|
|
1314
|
+
});
|
|
1315
|
+
if (session.sourceIds.size > 0) {
|
|
1316
|
+
session.sourceId = session.sourceIds.values().next().value ?? session.sourceId;
|
|
1317
|
+
void this.applyAudioPolicy(session);
|
|
1318
|
+
return;
|
|
1319
|
+
}
|
|
1320
|
+
this.sessions.delete(session.sessionKey);
|
|
1321
|
+
void this.disposeSession(session);
|
|
1322
|
+
}
|
|
1323
|
+
getSession(sourceId) {
|
|
1324
|
+
const sessionKey = this.sourceSessionKeys.get(sourceId);
|
|
1325
|
+
return sessionKey ? this.sessions.get(sessionKey) : void 0;
|
|
1326
|
+
}
|
|
1327
|
+
snapshotFromSession(session) {
|
|
1328
|
+
return {
|
|
1329
|
+
status: session.status,
|
|
1330
|
+
error: session.error
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
emitSessionSnapshot(session, snapshot) {
|
|
1334
|
+
session.sourceIds.forEach((sourceId) => this.emitSnapshot(sourceId, snapshot));
|
|
1335
|
+
}
|
|
1336
|
+
emitSessionTrtcEvent(session, type, rawType, payload) {
|
|
1337
|
+
session.sourceIds.forEach((sourceId) => this.emitTrtcEvent(sourceId, type, rawType, payload));
|
|
1338
|
+
}
|
|
1339
|
+
createSession(sourceId, trtc, aiDenoiser) {
|
|
1290
1340
|
return {
|
|
1341
|
+
sessionKey: buildTrtcSessionKey(trtc, aiDenoiser),
|
|
1291
1342
|
sourceId,
|
|
1343
|
+
sourceIds: /* @__PURE__ */ new Set([sourceId]),
|
|
1292
1344
|
trtc,
|
|
1345
|
+
aiDenoiser,
|
|
1293
1346
|
TRTC: null,
|
|
1294
1347
|
client: null,
|
|
1295
1348
|
connectPromise: null,
|
|
@@ -1315,7 +1368,7 @@ var TrtcSourceManager = class {
|
|
|
1315
1368
|
}
|
|
1316
1369
|
session.status = "connecting";
|
|
1317
1370
|
session.error = void 0;
|
|
1318
|
-
this.
|
|
1371
|
+
this.emitSessionSnapshot(session, {
|
|
1319
1372
|
status: session.status
|
|
1320
1373
|
});
|
|
1321
1374
|
session.connectPromise = (async () => {
|
|
@@ -1344,7 +1397,7 @@ var TrtcSourceManager = class {
|
|
|
1344
1397
|
session.views.forEach((binding) => {
|
|
1345
1398
|
void this.startRemoteVideoForBinding(client, event.userId, event.streamType, binding, remoteVideoKey);
|
|
1346
1399
|
});
|
|
1347
|
-
this.
|
|
1400
|
+
this.emitSessionTrtcEvent(session, "remote_video_available", TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, event);
|
|
1348
1401
|
};
|
|
1349
1402
|
const onRemoteVideoUnavailable = (event) => {
|
|
1350
1403
|
this.log("info", `\u8FDC\u7AEF\u89C6\u9891\u4E0D\u53EF\u7528 source=${session.sourceId} userId=${event.userId} streamType=${event.streamType}`);
|
|
@@ -1358,19 +1411,19 @@ var TrtcSourceManager = class {
|
|
|
1358
1411
|
userId: event.userId,
|
|
1359
1412
|
streamType: event.streamType
|
|
1360
1413
|
}).catch(() => void 0);
|
|
1361
|
-
this.
|
|
1414
|
+
this.emitSessionTrtcEvent(session, "remote_video_unavailable", TRTC.EVENT.REMOTE_VIDEO_UNAVAILABLE, event);
|
|
1362
1415
|
};
|
|
1363
1416
|
const onRemoteAudioAvailable = (event) => {
|
|
1364
1417
|
this.log("info", `\u8FDC\u7AEF\u97F3\u9891\u53EF\u7528 source=${session.sourceId} userId=${event.userId}`);
|
|
1365
1418
|
session.remoteAudioUsers.add(event.userId);
|
|
1366
1419
|
void this.applyAudioPolicy(session);
|
|
1367
|
-
this.
|
|
1420
|
+
this.emitSessionTrtcEvent(session, "remote_audio_available", TRTC.EVENT.REMOTE_AUDIO_AVAILABLE, event);
|
|
1368
1421
|
};
|
|
1369
1422
|
const onRemoteAudioUnavailable = (event) => {
|
|
1370
1423
|
this.log("info", `\u8FDC\u7AEF\u97F3\u9891\u4E0D\u53EF\u7528 source=${session.sourceId} userId=${event.userId}`);
|
|
1371
1424
|
session.remoteAudioUsers.delete(event.userId);
|
|
1372
1425
|
void this.applyAudioPolicy(session);
|
|
1373
|
-
this.
|
|
1426
|
+
this.emitSessionTrtcEvent(session, "remote_audio_unavailable", TRTC.EVENT.REMOTE_AUDIO_UNAVAILABLE, event);
|
|
1374
1427
|
};
|
|
1375
1428
|
session.onRemoteVideoAvailable = onRemoteVideoAvailable;
|
|
1376
1429
|
session.onRemoteVideoUnavailable = onRemoteVideoUnavailable;
|
|
@@ -1395,7 +1448,8 @@ var TrtcSourceManager = class {
|
|
|
1395
1448
|
session.status = "connected";
|
|
1396
1449
|
session.error = void 0;
|
|
1397
1450
|
this.log("info", `\u8FDB\u623F\u6210\u529F source=${session.sourceId} room=${roomId}`);
|
|
1398
|
-
this.
|
|
1451
|
+
await this.applyAIDenoiserPolicy(session, client, sdkAppId, userId, userSig);
|
|
1452
|
+
this.emitSessionSnapshot(session, {
|
|
1399
1453
|
status: session.status
|
|
1400
1454
|
});
|
|
1401
1455
|
await this.applyAudioPolicy(session);
|
|
@@ -1403,7 +1457,7 @@ var TrtcSourceManager = class {
|
|
|
1403
1457
|
session.status = "error";
|
|
1404
1458
|
session.error = error instanceof Error ? error.message : String(error);
|
|
1405
1459
|
this.log("error", `\u8FDE\u63A5\u5931\u8D25 source=${session.sourceId} error=${session.error}`);
|
|
1406
|
-
this.
|
|
1460
|
+
this.emitSessionSnapshot(session, {
|
|
1407
1461
|
status: session.status,
|
|
1408
1462
|
error: session.error
|
|
1409
1463
|
});
|
|
@@ -1480,6 +1534,25 @@ var TrtcSourceManager = class {
|
|
|
1480
1534
|
await client.muteRemoteAudio(userId, false);
|
|
1481
1535
|
}
|
|
1482
1536
|
}
|
|
1537
|
+
async applyAIDenoiserPolicy(session, client, sdkAppId, userId, userSig) {
|
|
1538
|
+
const options = resolveAIDenoiserOptions(session.aiDenoiser ?? this.aiDenoiser);
|
|
1539
|
+
if (!options.enabled) {
|
|
1540
|
+
this.log("info", `TRTC AIDenoiser \u5DF2\u5173\u95ED source=${session.sourceId}`);
|
|
1541
|
+
return;
|
|
1542
|
+
}
|
|
1543
|
+
try {
|
|
1544
|
+
await client.startPlugin("AIDenoiser", {
|
|
1545
|
+
sdkAppId,
|
|
1546
|
+
userId,
|
|
1547
|
+
userSig,
|
|
1548
|
+
mode: getAIDenoiserModeValue(options.mode),
|
|
1549
|
+
...options.assetsPath ? { assetsPath: options.assetsPath } : {}
|
|
1550
|
+
});
|
|
1551
|
+
this.log("info", `TRTC AIDenoiser \u5DF2\u5F00\u542F source=${session.sourceId} mode=${options.mode}`);
|
|
1552
|
+
} catch (error) {
|
|
1553
|
+
this.log("warn", `TRTC AIDenoiser \u5F00\u542F\u5931\u8D25 source=${session.sourceId}`, error);
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1483
1556
|
/**
|
|
1484
1557
|
* 销毁单个 source 会话:
|
|
1485
1558
|
* 解绑事件、停止远端视频、退出房间并销毁客户端。
|
|
@@ -1561,6 +1634,25 @@ function isRuntimeTrtcSource(source) {
|
|
|
1561
1634
|
function isSameTrtcConfig(a, b) {
|
|
1562
1635
|
return a.app_id === b.app_id && a.user_id === b.user_id && a.user_sig === b.user_sig && a.room_id === b.room_id;
|
|
1563
1636
|
}
|
|
1637
|
+
function buildTrtcSessionKey(trtc, aiDenoiser) {
|
|
1638
|
+
const denoiser = resolveAIDenoiserOptions(aiDenoiser);
|
|
1639
|
+
return JSON.stringify({
|
|
1640
|
+
appId: trtc.app_id,
|
|
1641
|
+
roomId: trtc.room_id,
|
|
1642
|
+
userId: trtc.user_id,
|
|
1643
|
+
userSig: trtc.user_sig,
|
|
1644
|
+
aiDenoiser: {
|
|
1645
|
+
enabled: denoiser.enabled,
|
|
1646
|
+
mode: denoiser.mode,
|
|
1647
|
+
assetsPath: denoiser.assetsPath
|
|
1648
|
+
}
|
|
1649
|
+
});
|
|
1650
|
+
}
|
|
1651
|
+
function isSameAIDenoiserOptions(a, b) {
|
|
1652
|
+
const left = resolveAIDenoiserOptions(a);
|
|
1653
|
+
const right = resolveAIDenoiserOptions(b);
|
|
1654
|
+
return left.enabled === right.enabled && left.mode === right.mode && left.assetsPath === right.assetsPath;
|
|
1655
|
+
}
|
|
1564
1656
|
function shouldUseStringRoomId(roomId) {
|
|
1565
1657
|
if (!/^\d+$/.test(roomId)) {
|
|
1566
1658
|
return true;
|
|
@@ -1572,6 +1664,26 @@ function getTrtcString(trtc, key) {
|
|
|
1572
1664
|
const value = trtc[key];
|
|
1573
1665
|
return typeof value === "string" ? value : "";
|
|
1574
1666
|
}
|
|
1667
|
+
function resolveAIDenoiserOptions(options) {
|
|
1668
|
+
if (options === false) {
|
|
1669
|
+
return {
|
|
1670
|
+
...DEFAULT_DENOISER_OPTIONS,
|
|
1671
|
+
enabled: false
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
if (options === true || options === void 0) {
|
|
1675
|
+
return DEFAULT_DENOISER_OPTIONS;
|
|
1676
|
+
}
|
|
1677
|
+
return {
|
|
1678
|
+
...DEFAULT_DENOISER_OPTIONS,
|
|
1679
|
+
...options,
|
|
1680
|
+
enabled: options.enabled ?? DEFAULT_DENOISER_OPTIONS.enabled,
|
|
1681
|
+
mode: options.mode ?? DEFAULT_DENOISER_OPTIONS.mode
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
function getAIDenoiserModeValue(mode) {
|
|
1685
|
+
return mode === "far_field_reduction" ? 1 : 0;
|
|
1686
|
+
}
|
|
1575
1687
|
function buildRemoteVideoKey(userId, streamType) {
|
|
1576
1688
|
return `${userId}::${streamType}`;
|
|
1577
1689
|
}
|
|
@@ -2074,7 +2186,8 @@ var IviRuntimeCoordinator = class {
|
|
|
2074
2186
|
};
|
|
2075
2187
|
this.trtcSourceManager = new TrtcSourceManager(
|
|
2076
2188
|
this.config.onLog,
|
|
2077
|
-
(event) => this.emitTrtcEvent(event)
|
|
2189
|
+
(event) => this.emitTrtcEvent(event),
|
|
2190
|
+
this.config.trtcAIDenoiser
|
|
2078
2191
|
);
|
|
2079
2192
|
this.livekitSourceManager = new LivekitSourceManager(this.config.onLog);
|
|
2080
2193
|
this.sessionHandler = new SessionEventHandler(this.sessionManager, {
|
|
@@ -3154,7 +3267,8 @@ function IVITrtcPlayer(props) {
|
|
|
3154
3267
|
style,
|
|
3155
3268
|
loadingFallback = null,
|
|
3156
3269
|
errorFallback = null,
|
|
3157
|
-
muted = false
|
|
3270
|
+
muted = false,
|
|
3271
|
+
trtcAIDenoiser
|
|
3158
3272
|
} = props;
|
|
3159
3273
|
const containerRef = useRef(null);
|
|
3160
3274
|
const viewIdRef = useRef(`trtc-view-${Math.random().toString(36).slice(2, 10)}`);
|
|
@@ -3175,7 +3289,7 @@ function IVITrtcPlayer(props) {
|
|
|
3175
3289
|
}
|
|
3176
3290
|
let disposed = false;
|
|
3177
3291
|
if (shouldManageSourceLifecycle) {
|
|
3178
|
-
manager.upsertSource(resolvedSourceId, trtc);
|
|
3292
|
+
manager.upsertSource(resolvedSourceId, trtc, trtcAIDenoiser);
|
|
3179
3293
|
}
|
|
3180
3294
|
const unsubscribe = manager.subscribe(resolvedSourceId, (snapshot) => {
|
|
3181
3295
|
if (disposed) {
|
|
@@ -3206,7 +3320,8 @@ function IVITrtcPlayer(props) {
|
|
|
3206
3320
|
trtc.app_id,
|
|
3207
3321
|
trtc.room_id,
|
|
3208
3322
|
trtc.user_id,
|
|
3209
|
-
trtc.user_sig
|
|
3323
|
+
trtc.user_sig,
|
|
3324
|
+
trtcAIDenoiser
|
|
3210
3325
|
]);
|
|
3211
3326
|
useEffect(() => {
|
|
3212
3327
|
manager.updateViewMuted(resolvedSourceId, viewIdRef.current, muted);
|